演算をdouble対応にした
This commit is contained in:
@@ -112,7 +112,7 @@ class PrintCode : Code
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//type mismatch
|
//type mismatch
|
||||||
break;
|
throw new TypeMismatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,6 +195,25 @@ class Operate : Code
|
|||||||
Value l;
|
Value l;
|
||||||
Value r;
|
Value r;
|
||||||
vm.pop(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);
|
vm.pop(l);
|
||||||
if(l.type == ValueType.String)
|
if(l.type == ValueType.String)
|
||||||
{
|
{
|
||||||
@@ -232,7 +251,6 @@ class Operate : Code
|
|||||||
}
|
}
|
||||||
if(r.type == ValueType.Integer || r.type == ValueType.Double)
|
if(r.type == ValueType.Integer || r.type == ValueType.Double)
|
||||||
{
|
{
|
||||||
double rd = r.integerValue;
|
|
||||||
switch(operator)
|
switch(operator)
|
||||||
{
|
{
|
||||||
//数値 * 文字列だとエラー
|
//数値 * 文字列だとエラー
|
||||||
@@ -260,9 +278,12 @@ class Operate : Code
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int li = l.integerValue;
|
int li = l.integerValue;
|
||||||
int ri = r.integerValue;
|
|
||||||
double ld = l.integerValue;
|
double ld = l.integerValue;
|
||||||
double rd = r.integerValue;
|
if(l.type == ValueType.Double)
|
||||||
|
{
|
||||||
|
li = cast(int)l.doubleValue;
|
||||||
|
ld = l.doubleValue;
|
||||||
|
}
|
||||||
//とりあえずInteger
|
//とりあえずInteger
|
||||||
switch(operator)
|
switch(operator)
|
||||||
{
|
{
|
||||||
@@ -278,41 +299,58 @@ class Operate : Code
|
|||||||
case TokenType.Div:
|
case TokenType.Div:
|
||||||
ld /= rd;
|
ld /= rd;
|
||||||
break;
|
break;
|
||||||
|
case TokenType.IntDiv:
|
||||||
|
//TODO:範囲外だとOverflow
|
||||||
|
vm.push(Value(cast(int)(ld / rd)));
|
||||||
|
return;
|
||||||
case TokenType.Mod:
|
case TokenType.Mod:
|
||||||
ld %= rd;
|
ld %= rd;
|
||||||
break;
|
break;
|
||||||
case TokenType.And:
|
case TokenType.And:
|
||||||
ld = li & ri;
|
vm.push(Value(li & ri));
|
||||||
break;
|
return;
|
||||||
case TokenType.Or:
|
case TokenType.Or:
|
||||||
ld = li | ri;
|
vm.push(Value(li | ri));
|
||||||
break;
|
return;
|
||||||
|
case TokenType.LogicalAnd:
|
||||||
|
vm.push(Value(li && ri));
|
||||||
|
return;
|
||||||
|
case TokenType.LogicalOr:
|
||||||
|
vm.push(Value(li || ri));
|
||||||
|
return;
|
||||||
case TokenType.Xor:
|
case TokenType.Xor:
|
||||||
ld = li ^ ri;
|
vm.push(Value(li ^ ri));
|
||||||
break;
|
return;
|
||||||
case TokenType.Equal:
|
case TokenType.Equal:
|
||||||
ld = ld == rd;
|
vm.push(Value(li == ri));
|
||||||
break;
|
return;
|
||||||
case TokenType.NotEqual:
|
case TokenType.NotEqual:
|
||||||
ld = ld != rd;
|
vm.push(Value(li != ri));
|
||||||
break;
|
return;
|
||||||
case TokenType.Less:
|
case TokenType.Less:
|
||||||
ld = ld < rd;
|
vm.push(Value(li < ri));
|
||||||
break;
|
return;
|
||||||
case TokenType.LessEqual:
|
case TokenType.LessEqual:
|
||||||
ld = ld <= rd;
|
vm.push(Value(li <= ri));
|
||||||
break;
|
return;
|
||||||
case TokenType.Greater:
|
case TokenType.Greater:
|
||||||
ld = ld > rd;
|
vm.push(Value(li > ri));
|
||||||
break;
|
return;
|
||||||
case TokenType.GreaterEqual:
|
case TokenType.GreaterEqual:
|
||||||
ld = ld >= rd;
|
vm.push(Value(li >= ri));
|
||||||
break;
|
return;
|
||||||
|
case TokenType.LeftShift:
|
||||||
|
vm.push(Value(li << ri));
|
||||||
|
return;
|
||||||
|
case TokenType.RightShift:
|
||||||
|
vm.push(Value(li >> ri));
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
writeln("NotImpl: ", operator);
|
writeln("NotImpl: ", operator);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
l.integerValue = cast(int)ld;
|
l.type = ValueType.Double;
|
||||||
|
l.doubleValue = ld;
|
||||||
vm.push(l);
|
vm.push(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import otya.smilebasic.node;
|
|||||||
import otya.smilebasic.token;
|
import otya.smilebasic.token;
|
||||||
import otya.smilebasic.vm;
|
import otya.smilebasic.vm;
|
||||||
import otya.smilebasic.type;
|
import otya.smilebasic.type;
|
||||||
|
import otya.smilebasic.error;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
class Compiler
|
class Compiler
|
||||||
{
|
{
|
||||||
@@ -75,6 +76,7 @@ class Compiler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//error:二重定義
|
//error:二重定義
|
||||||
|
throw new DuplicateVariable();
|
||||||
}
|
}
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|||||||
38
SMILEBASIC/error.d
Normal file
38
SMILEBASIC/error.d
Normal file
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ class Lexical
|
|||||||
table['='] = TokenType.Assign;
|
table['='] = TokenType.Assign;
|
||||||
table['<'] = TokenType.Less;
|
table['<'] = TokenType.Less;
|
||||||
table['>'] = TokenType.Greater;
|
table['>'] = TokenType.Greater;
|
||||||
|
table['!'] = TokenType.LogicalNot;
|
||||||
reserved["OR"] = TokenType.Or;
|
reserved["OR"] = TokenType.Or;
|
||||||
reserved["AND"] = TokenType.And;
|
reserved["AND"] = TokenType.And;
|
||||||
reserved["XOR"] = TokenType.Xor;
|
reserved["XOR"] = TokenType.Xor;
|
||||||
@@ -175,6 +176,30 @@ class Lexical
|
|||||||
i += 2;
|
i += 2;
|
||||||
break;
|
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)
|
if(table[cast(char)c] == TokenType.Unknown)
|
||||||
{
|
{
|
||||||
//error
|
//error
|
||||||
@@ -254,7 +279,9 @@ class Parser
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
// return 8;//&&,||
|
case TokenType.LogicalAnd:
|
||||||
|
case TokenType.LogicalOr:
|
||||||
|
return 8;//&&,||
|
||||||
case TokenType.And:
|
case TokenType.And:
|
||||||
case TokenType.Or:
|
case TokenType.Or:
|
||||||
case TokenType.Xor:
|
case TokenType.Xor:
|
||||||
@@ -266,13 +293,15 @@ class Parser
|
|||||||
case TokenType.Greater:
|
case TokenType.Greater:
|
||||||
case TokenType.GreaterEqual:
|
case TokenType.GreaterEqual:
|
||||||
return 6;//==,!=,<,<=,>,>=
|
return 6;//==,!=,<,<=,>,>=
|
||||||
|
case TokenType.LeftShift:
|
||||||
// return 5;//<<,>>
|
case TokenType.RightShift:
|
||||||
|
return 5;//<<,>>
|
||||||
case TokenType.Plus:
|
case TokenType.Plus:
|
||||||
case TokenType.Minus:
|
case TokenType.Minus:
|
||||||
return 4;//+,-(bin)
|
return 4;//+,-(bin)
|
||||||
case TokenType.Mul:
|
case TokenType.Mul:
|
||||||
case TokenType.Div:
|
case TokenType.Div:
|
||||||
|
case TokenType.IntDiv:
|
||||||
case TokenType.Mod:
|
case TokenType.Mod:
|
||||||
return 3;//*,/,DIV,MOD
|
return 3;//*,/,DIV,MOD
|
||||||
// return 2;//-,NOT,!
|
// return 2;//-,NOT,!
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ enum TokenType
|
|||||||
Greater,//>
|
Greater,//>
|
||||||
LessEqual,
|
LessEqual,
|
||||||
GreaterEqual,
|
GreaterEqual,
|
||||||
|
LeftShift,//<<
|
||||||
|
RightShift,//>>
|
||||||
|
LogicalNot,//!
|
||||||
|
LogicalAnd,//&&
|
||||||
|
LogicalOr,//||
|
||||||
|
IntDiv,//DIV
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user