diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index cf77528..f272de9 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -256,6 +256,10 @@ class Compiler { code ~= new Push(value); } + void genCodeImm(TokenValue value) + { + code ~= new Push(value.toSBImm); + } void genCodePushGlobal(int ind) { code ~= new PushG(ind); @@ -1132,7 +1136,7 @@ class Compiler { auto data = cast(Data)i; foreach(j; data.data) - s.data.addData(j); + s.data.addData(j.toSBImm); } break; case NodeType.Read: diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index 54ab14d..aa73b2b 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -60,8 +60,8 @@ abstract class Expression : Node } class Constant : Expression { - Value value; - this(Value v, SourceLocation loc) + TokenValue value; + this(TokenValue v, SourceLocation loc) { super.location = loc; this.type = NodeType.Constant; @@ -515,14 +515,14 @@ class Inc : Statement } class Data : Statement { - Value[] data; + TokenValue[] data; this(SourceLocation loc) { super.location = loc; this.type = NodeType.Data; - this.data = new Value[0]; + this.data = new TokenValue[0]; } - void addData(Value v) + void addData(TokenValue v) { data ~= v; } diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index abd32ac..7aa2d98 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -168,11 +168,11 @@ class Lexical num = numstr.to!double; if(num <= int.max && num >= int.min && !dot) { - token = Token(TokenType.Integer, Value(cast(int)num)); + token = Token(TokenType.Integer, TokenValue(cast(int)num)); } else { - token = Token(TokenType.Integer, Value(num)); + token = Token(TokenType.Integer, TokenValue(num)); } break; } @@ -199,17 +199,17 @@ class Lexical //TRUE/FALSEは3.1でもDATAに使える定数 if(r == TokenType.True) { - token = Token(TokenType.Integer, Value(1)); + token = Token(TokenType.Integer, TokenValue(1)); break; } if(r == TokenType.False) { - token = Token(TokenType.Integer, Value(0)); + token = Token(TokenType.Integer, TokenValue(0)); break; } if(r != TokenType.Unknown) { - token = Token(r, Value(iden)); + token = Token(r, TokenValue(iden)); break; } } @@ -226,7 +226,7 @@ class Lexical } else { - token = Token(TokenType.Iden, Value(iden)); + token = Token(TokenType.Iden, TokenValue(iden)); break; } } @@ -245,7 +245,7 @@ class Lexical } str ~= c; } - token = Token(TokenType.String, Value(str)); + token = Token(TokenType.String, TokenValue(str)); break; } if(c == '@' || c == '#') @@ -267,11 +267,11 @@ class Lexical } if (isLabel) { - token = Token(TokenType.Label, Value(iden)); + token = Token(TokenType.Label, TokenValue(iden)); } else { - token = Token(TokenType.Constant, Value(std.uni.toUpper(iden))); + token = Token(TokenType.Constant, TokenValue(std.uni.toUpper(iden))); } break; } @@ -327,7 +327,7 @@ class Lexical } wstring numstr = code[start..i]; int num = numstr.to!uint(16); - token = Token(TokenType.Integer, Value(num)); + token = Token(TokenType.Integer, TokenValue(num)); break; } if(code[i + 1].toUpper == 'B') @@ -344,7 +344,7 @@ class Lexical } wstring numstr = code[start..i]; int num = numstr.to!uint(2); - token = Token(TokenType.Integer, Value(num)); + token = Token(TokenType.Integer, TokenValue(num)); break; } if(code[i + 1] == '&') @@ -1324,11 +1324,11 @@ class Parser } else { - expr = new Constant(Value(1), lex.location); + expr = new Constant(TokenValue(1), lex.location); } if(dec) { - expr = new BinaryOperator(new Constant(Value(0), lex.location), TokenType.Minus, expr, lex.location); + expr = new BinaryOperator(new Constant(TokenValue(0), lex.location), TokenType.Minus, expr, lex.location); } return new Inc(var, expr, lex.location); } @@ -1482,7 +1482,7 @@ class Parser else { //とりあえず - step = new Constant(Value(1), lex.location); + step = new Constant(TokenValue(1), lex.location); } token = lex.front(); Statements statements = forStatements(); @@ -1712,7 +1712,7 @@ class Parser return print; } //compilerでやるべきな気がする - bool constcalc(Value left, Value right, TokenType type, out double result) + bool constcalc(TokenValue left, TokenValue right, TokenType type, out double result) { switch (type) { @@ -1797,7 +1797,7 @@ class Parser { if (constcalc(leftconst.value, rightconst.value, op.operator, result)) { - auto l = new Constant(Value(result), lex.location); + auto l = new Constant(TokenValue(result), lex.location); constexpr = true; if(order != getOPRank(token.type)) return l; @@ -1898,14 +1898,14 @@ class Parser lex.popFront(); auto a = term(2/*array*/, null); double result; - if (a.type == NodeType.Constant && constcalc(Value(0), (cast(Constant)a).value, TokenType.Minus, result)) + if (a.type == NodeType.Constant && constcalc(TokenValue(0), (cast(Constant)a).value, TokenType.Minus, result)) { - node = new Constant(Value(result), lex.location); + node = new Constant(TokenValue(result), lex.location); return node; } else { - node = new BinaryOperator(new Constant(Value(0), lex.location), TokenType.Minus, a, lex.location); + node = new BinaryOperator(new Constant(TokenValue(0), lex.location), TokenType.Minus, a, lex.location); return node; } } @@ -1918,7 +1918,7 @@ class Parser { if (token.value.castString in constant) { - node = new Constant(Value(constant[token.value.castString]), lex.location); + node = new Constant(TokenValue(constant[token.value.castString]), lex.location); } else { diff --git a/SMILEBASIC/token.d b/SMILEBASIC/token.d index a22ea16..ff54d29 100644 --- a/SMILEBASIC/token.d +++ b/SMILEBASIC/token.d @@ -1,5 +1,6 @@ module otya.smilebasic.token; import otya.smilebasic.type; +import std.exception; enum TokenType { Unknown, @@ -77,11 +78,142 @@ enum TokenType Constant, } +enum TokenValueType +{ + integer, + double_, + string_ +} +struct TokenValue +{ + TokenValueType type; + private union + { + int integer; + wstring string_; + double double_; + } + ref integerValue() + { + enforce(type == TokenValueType.integer); + return integer; + } + int integerValue(int val) + { + enforce(type == TokenValueType.integer); + return integer = val; + } + ref stringValue() + { + enforce(type == TokenValueType.string_); + return string_; + } + wstring stringValue(wstring val) + { + enforce(type == TokenValueType.string_); + return string_ = val; + } + ref doubleValue() + { + enforce(type == TokenValueType.double_); + return double_; + } + double doubleValue(double val) + { + enforce(type == TokenValueType.double_); + return double_ = val; + } + int castInteger() + { + switch (type) + { + case TokenValueType.integer: + return integer; + case TokenValueType.double_: + return cast(int)double_; + default: + assert(false); + } + } + double castDouble() + { + switch (type) + { + case TokenValueType.integer: + return integer; + case TokenValueType.double_: + return double_; + default: + assert(false); + } + } + wstring castString() + { + switch (type) + { + case TokenValueType.string_: + return string_; + default: + assert(false); + } + } + bool isNumber() + { + switch (type) + { + case TokenValueType.integer: + case TokenValueType.double_: + return true; + default: + return false; + } + } + bool isString() + { + switch (type) + { + case TokenValueType.string_: + return true; + default: + return false; + } + } + this(int v) + { + type = TokenValueType.integer; + integer = v; + } + this(wstring v) + { + type = TokenValueType.string_; + string_ = v; + } + this(double v) + { + type = TokenValueType.double_; + double_ = v; + } + Value toSBImm() + { + switch (type) + { + case TokenValueType.integer: + return Value(integer); + case TokenValueType.string_: + return Value(string_); + case TokenValueType.double_: + return Value(double_); + default: + assert(false); + } + } +} + struct Token { TokenType type; - Value value; - this(TokenType t, Value v) + TokenValue value; + this(TokenType t, TokenValue v) { type = t; value = v;