diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index a1ea627..04eb517 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -112,7 +112,7 @@ class PrintCode : Code break; default: //type mismatch - break; + throw new TypeMismatch(); } } } @@ -195,6 +195,25 @@ class Operate : Code Value l; Value r; vm.pop(r); + int ri = r.integerValue; + double rd = r.integerValue; + if(r.type == ValueType.Double) + { + ri = cast(int)r.doubleValue; + rd = r.doubleValue; + } + switch(operator) + { + //単項演算子 + case TokenType.Not: + vm.push(Value(~ri)); + return; + case TokenType.LogicalNot: + vm.push(Value(!ri)); + return; + default: + break; + } vm.pop(l); if(l.type == ValueType.String) { @@ -232,7 +251,6 @@ class Operate : Code } if(r.type == ValueType.Integer || r.type == ValueType.Double) { - double rd = r.integerValue; switch(operator) { //数値 * 文字列だとエラー @@ -260,9 +278,12 @@ class Operate : Code } } int li = l.integerValue; - int ri = r.integerValue; double ld = l.integerValue; - double rd = r.integerValue; + if(l.type == ValueType.Double) + { + li = cast(int)l.doubleValue; + ld = l.doubleValue; + } //とりあえずInteger switch(operator) { @@ -278,41 +299,58 @@ class Operate : Code case TokenType.Div: ld /= rd; break; + case TokenType.IntDiv: + //TODO:範囲外だとOverflow + vm.push(Value(cast(int)(ld / rd))); + return; case TokenType.Mod: ld %= rd; break; case TokenType.And: - ld = li & ri; - break; + vm.push(Value(li & ri)); + return; case TokenType.Or: - ld = li | ri; - break; + vm.push(Value(li | ri)); + return; + case TokenType.LogicalAnd: + vm.push(Value(li && ri)); + return; + case TokenType.LogicalOr: + vm.push(Value(li || ri)); + return; case TokenType.Xor: - ld = li ^ ri; - break; + vm.push(Value(li ^ ri)); + return; case TokenType.Equal: - ld = ld == rd; - break; + vm.push(Value(li == ri)); + return; case TokenType.NotEqual: - ld = ld != rd; - break; + vm.push(Value(li != ri)); + return; case TokenType.Less: - ld = ld < rd; - break; + vm.push(Value(li < ri)); + return; case TokenType.LessEqual: - ld = ld <= rd; - break; + vm.push(Value(li <= ri)); + return; case TokenType.Greater: - ld = ld > rd; - break; + vm.push(Value(li > ri)); + return; case TokenType.GreaterEqual: - ld = ld >= rd; - break; + vm.push(Value(li >= ri)); + return; + case TokenType.LeftShift: + vm.push(Value(li << ri)); + return; + case TokenType.RightShift: + vm.push(Value(li >> ri)); + return; default: writeln("NotImpl: ", operator); break; } - l.integerValue = cast(int)ld; + l.type = ValueType.Double; + l.doubleValue = ld; vm.push(l); } } diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 9aceb51..3cebc76 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -3,6 +3,7 @@ import otya.smilebasic.node; import otya.smilebasic.token; import otya.smilebasic.vm; import otya.smilebasic.type; +import otya.smilebasic.error; import std.stdio; class Compiler { @@ -75,6 +76,7 @@ class Compiler else { //error:二重定義 + throw new DuplicateVariable(); } return global; } diff --git a/SMILEBASIC/error.d b/SMILEBASIC/error.d new file mode 100644 index 0000000..f3fadd2 --- /dev/null +++ b/SMILEBASIC/error.d @@ -0,0 +1,38 @@ +module otya.smilebasic.error; +import std.exception; +import std.string; +class SmileBasicError : Exception +{ + int errnum; + int errline; + int errprg; + this(int slot, int line, string message) + { + super(format("%s in %d:%d", message, slot, line)); + } + this(int line, string message) + { + super(format("%s in %d", message, line)); + } + this(string message) + { + super(message); + } +} +class TypeMismatch : SmileBasicError +{ + this() + { + this.errnum = 8; + super("Type mismatch"); + } +} +class DuplicateVariable : SmileBasicError +{ + this() + { + this.errnum = 18; + super("Duplicate variable"); + } +} + diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 277c8f9..2865d63 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -35,6 +35,7 @@ class Lexical table['='] = TokenType.Assign; table['<'] = TokenType.Less; table['>'] = TokenType.Greater; + table['!'] = TokenType.LogicalNot; reserved["OR"] = TokenType.Or; reserved["AND"] = TokenType.And; reserved["XOR"] = TokenType.Xor; @@ -175,6 +176,30 @@ class Lexical i += 2; break; } + if(c == '<' && i + 1 < code.length && code[i + 1] == '<') + { + token = Token(TokenType.LeftShift); + i += 2; + break; + } + if(c == '>' && i + 1 < code.length && code[i + 1] == '>') + { + token = Token(TokenType.RightShift); + i += 2; + break; + } + if(c == '&' && i + 1 < code.length && code[i + 1] == '&') + { + token = Token(TokenType.LogicalAnd); + i += 2; + break; + } + if(c == '|' && i + 1 < code.length && code[i + 1] == '|') + { + token = Token(TokenType.LogicalOr); + i += 2; + break; + } if(table[cast(char)c] == TokenType.Unknown) { //error @@ -254,7 +279,9 @@ class Parser { switch(type) { -// return 8;//&&,|| + case TokenType.LogicalAnd: + case TokenType.LogicalOr: + return 8;//&&,|| case TokenType.And: case TokenType.Or: case TokenType.Xor: @@ -266,13 +293,15 @@ class Parser case TokenType.Greater: case TokenType.GreaterEqual: return 6;//==,!=,<,<=,>,>= - -// return 5;//<<,>> + case TokenType.LeftShift: + case TokenType.RightShift: + return 5;//<<,>> case TokenType.Plus: case TokenType.Minus: return 4;//+,-(bin) case TokenType.Mul: case TokenType.Div: + case TokenType.IntDiv: case TokenType.Mod: return 3;//*,/,DIV,MOD // return 2;//-,NOT,! diff --git a/SMILEBASIC/token.d b/SMILEBASIC/token.d index 89895bc..e5eea76 100644 --- a/SMILEBASIC/token.d +++ b/SMILEBASIC/token.d @@ -38,6 +38,12 @@ enum TokenType Greater,//> LessEqual, GreaterEqual, + LeftShift,//<< + RightShift,//>> + LogicalNot,//! + LogicalAnd,//&& + LogicalOr,//|| + IntDiv,//DIV } struct Token