Skip to content

Commit 2437239

Browse files
committed
#261 DATA statement now supports labels
1 parent 7d91f7a commit 2437239

4 files changed

Lines changed: 111 additions & 56 deletions

File tree

modules/xcb-module-grammar

source/compiler/variable.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -731,9 +731,9 @@ class VariableAccess : AccessorInterface
731731
}
732732

733733
// optimize if variable length is power of two
734-
if(ceil(log2(varLen)) == floor(log2(varLen))) {
734+
if(ceil(log2(to!float(varLen))) == floor(log2(to!float(varLen)))) {
735735
if(varLen > 1) { // No need to do anything if it's 1
736-
asmCode ~= " lshift" ~ indexTypeName ~ "wconst " ~ to!string(log2(varLen)) ~ "\n";
736+
asmCode ~= " lshift" ~ indexTypeName ~ "wconst " ~ to!string(log2(to!float(varLen))) ~ "\n";
737737
}
738738
}
739739
else {

source/language/grammar.d

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ struct GenericXCBASIC(TParseTree)
178178
rules["Number"] = toDelegate(&Number);
179179
rules["Label"] = toDelegate(&Label);
180180
rules["Label_ref"] = toDelegate(&Label_ref);
181+
rules["Label_deref"] = toDelegate(&Label_deref);
181182
rules["Line_id"] = toDelegate(&Line_id);
182183
rules["Reserved"] = toDelegate(&Reserved);
183184
rules["WS"] = toDelegate(&WS);
@@ -4385,15 +4386,15 @@ struct GenericXCBASIC(TParseTree)
43854386
{
43864387
if(__ctfe)
43874388
{
4388-
return pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_ref), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_ref), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist")(p);
4389+
return pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist")(p);
43894390
}
43904391
else
43914392
{
43924393
if (auto m = tuple(`Datalist`, p.end) in memo)
43934394
return *m;
43944395
else
43954396
{
4396-
TParseTree result = hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_ref), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_ref), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist"), "Datalist")(p);
4397+
TParseTree result = hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist"), "Datalist")(p);
43974398
memo[tuple(`Datalist`, p.end)] = result;
43984399
return result;
43994400
}
@@ -4404,12 +4405,12 @@ struct GenericXCBASIC(TParseTree)
44044405
{
44054406
if(__ctfe)
44064407
{
4407-
return pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_ref), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_ref), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist")(TParseTree("", false,[], s));
4408+
return pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist")(TParseTree("", false,[], s));
44084409
}
44094410
else
44104411
{
44114412
forgetMemo();
4412-
return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_ref), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_ref), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist"), "Datalist")(TParseTree("", false,[], s));
4413+
return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.zeroOrMore!(pegged.peg.and!(pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.literal!(","), pegged.peg.discard!(pegged.peg.option!(WS)), pegged.peg.or!(Number, String, Label_deref, Varname), pegged.peg.discard!(pegged.peg.option!(WS))))), "XCBASIC.Datalist"), "Datalist")(TParseTree("", false,[], s));
44134414
}
44144415
}
44154416
static string Datalist(GetName g)
@@ -5666,6 +5667,42 @@ struct GenericXCBASIC(TParseTree)
56665667
return "XCBASIC.Label_ref";
56675668
}
56685669

5670+
static TParseTree Label_deref(TParseTree p)
5671+
{
5672+
if(__ctfe)
5673+
{
5674+
return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("@"), Label_ref), "XCBASIC.Label_deref")(p);
5675+
}
5676+
else
5677+
{
5678+
if (auto m = tuple(`Label_deref`, p.end) in memo)
5679+
return *m;
5680+
else
5681+
{
5682+
TParseTree result = hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("@"), Label_ref), "XCBASIC.Label_deref"), "Label_deref")(p);
5683+
memo[tuple(`Label_deref`, p.end)] = result;
5684+
return result;
5685+
}
5686+
}
5687+
}
5688+
5689+
static TParseTree Label_deref(string s)
5690+
{
5691+
if(__ctfe)
5692+
{
5693+
return pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("@"), Label_ref), "XCBASIC.Label_deref")(TParseTree("", false,[], s));
5694+
}
5695+
else
5696+
{
5697+
forgetMemo();
5698+
return hooked!(pegged.peg.defined!(pegged.peg.and!(pegged.peg.literal!("@"), Label_ref), "XCBASIC.Label_deref"), "Label_deref")(TParseTree("", false,[], s));
5699+
}
5700+
}
5701+
static string Label_deref(GetName g)
5702+
{
5703+
return "XCBASIC.Label_deref";
5704+
}
5705+
56695706
static TParseTree Line_id(TParseTree p)
56705707
{
56715708
if(__ctfe)

source/statement/data_stmt.d

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -46,75 +46,93 @@ class Data_stmt : Statement
4646
string[] listItems;
4747
bool truncated;
4848
ulong finalLength;
49-
float floatVal;
50-
int intVal;
49+
5150
foreach (datum; dataListNode.children) {
52-
if(type.name == Type.STRING) {
53-
if(datum.name != "XCBASIC.String") {
54-
compiler.displayError("Type mismatch: expected string, got number");
55-
}
56-
compiler.getImCode().appendSegment(
57-
inlineData ? IntermediateCode.PROGRAM_SEGMENT : IntermediateCode.DATA_SEGMENT,
58-
" " ~ asciiToPetsciiHex(join(datum.matches[1..$-1]), strLen, truncated, finalLength) ~ "\n"
59-
);
60-
if(truncated) {
61-
compiler.displayWarning("String truncated to " ~ to!string(strLen) ~ " characters");
62-
}
63-
}
64-
else {
65-
if(datum.name == "XCBASIC.String") {
66-
compiler.displayError("Type mismatch: expected number, got string");
67-
}
68-
if(datum.name == "XCBASIC.Number") {
51+
switch (datum.name) {
52+
case "XCBASIC.String":
53+
if (type.name != Type.STRING) {
54+
compiler.displayError("Type mismatch: expected number, label reference or constant, got string");
55+
}
56+
compiler.getImCode().appendSegment(
57+
inlineData ? IntermediateCode.PROGRAM_SEGMENT : IntermediateCode.DATA_SEGMENT,
58+
" " ~ asciiToPetsciiHex(join(datum.matches[1..$-1]), strLen, truncated, finalLength) ~ "\n"
59+
);
60+
if(truncated) {
61+
compiler.displayWarning("String truncated to " ~ to!string(strLen) ~ " characters");
62+
}
63+
break;
64+
65+
case "XCBASIC.Number":
66+
if (type.name == Type.STRING) {
67+
compiler.displayError("Type mismatch: expected string, got number");
68+
}
6969
Number num = new Number(datum, compiler, type.name == Type.FLOAT);
70-
floatVal = num.floatVal;
71-
intVal = num.intVal;
72-
} else {
73-
// A constant
70+
listItems ~= getNumberAsString(num.intVal, num.floatVal, type);
71+
break;
72+
73+
case "XCBASIC.Varname":
74+
if (type.name == Type.STRING) {
75+
compiler.displayError("Type mismatch: expected string, got constant");
76+
}
7477
Variable var = compiler.getVars().findVisible(datum.matches.join);
75-
if(var !is null) {
76-
if(!var.isConst) {
78+
if (var !is null) {
79+
if (!var.isConst) {
7780
compiler.displayError("DATA must be constant");
7881
}
79-
// a constant
80-
floatVal = var.constVal;
81-
intVal = to!int(var.constVal);
82+
listItems ~= getNumberAsString(to!int(var.constVal), var.constVal, type);
8283
}
8384
else {
8485
compiler.displayError("Unknown constant \"" ~ datum.matches.join ~ "\"");
8586
}
86-
}
87-
try {
88-
switch(type.name) {
89-
case Type.FLOAT:
90-
listItems ~= Number.floatToHex(floatVal, "$");
91-
break;
92-
93-
case Type.DEC:
94-
listItems ~= Number.getDecimalAsHex(intVal, "$");
95-
break;
96-
97-
default:
98-
listItems ~= Number.integralToHex(intVal, type, true, "$");
99-
break;
87+
break;
88+
89+
case "XCBASIC.Label_deref":
90+
if (type.name == Type.STRING) {
91+
compiler.displayError("Type mismatch: expected string, got label reference");
92+
}
93+
if (type.name != Type.UINT16 && type.name != Type.INT16) {
94+
compiler.displayError("Type mismatch: a label reference can only be part of INT or WORD data");
95+
}
96+
immutable string identifier = join(datum.children[0].matches);
97+
if (compiler.getLabels().exists(identifier, false)) {
98+
immutable string localLabel = compiler.getLabels().toAsmLabel(identifier);
99+
listItems ~= "<" ~ localLabel;
100+
listItems ~= ">" ~ localLabel;
101+
} else {
102+
compiler.displayError("Unknown label \"" ~ identifier ~ "\"");
100103
}
101-
}
102-
catch(Exception e) {
103-
compiler.displayError(e.msg);
104-
}
105-
104+
break;
105+
106+
default:
107+
assert(0);
106108
}
107109
}
108-
if(listItems.length > 0) {
110+
111+
if (listItems.length > 0) {
109112
foreach(chunk; chunks(listItems, 8)) {
110-
compiler.getImCode().appendSegment(
113+
compiler.getImCode().appendSegment(
111114
inlineData ? IntermediateCode.PROGRAM_SEGMENT : IntermediateCode.DATA_SEGMENT,
112115
" DC.B " ~ chunk.join(",") ~ "\n"
113116
);
114117
}
115118
}
116119
}
117120

121+
// Translates a numeric value to its string representation
122+
private string getNumberAsString(int intVal, float floatVal, Type type)
123+
{
124+
switch(type.name) {
125+
case Type.FLOAT:
126+
return Number.floatToHex(floatVal, "$");
127+
128+
case Type.DEC:
129+
return Number.getDecimalAsHex(intVal, "$");
130+
131+
default:
132+
return Number.integralToHex(intVal, type, true, "$");
133+
}
134+
}
135+
118136
// Immediately preceding labels should go to DATA segment
119137
override protected void dumpLabels()
120138
{

0 commit comments

Comments
 (0)