SWAPを実装
This commit is contained in:
@@ -1,3 +1,23 @@
|
|||||||
|
'SWAP TEST
|
||||||
|
SWAPTEST
|
||||||
|
DEF SWAPTEST
|
||||||
|
VAR A=1
|
||||||
|
VAR B=2
|
||||||
|
SWAP A,B
|
||||||
|
ASSERT__ B==1, "SWAP"
|
||||||
|
ASSERT__ A==2, "SWAP"
|
||||||
|
VAR A$="1
|
||||||
|
VAR B$="2
|
||||||
|
SWAP A$,B$
|
||||||
|
ASSERT__ B$=="1", "SWAP"
|
||||||
|
ASSERT__ A$=="2", "SWAP"
|
||||||
|
VAR A%=1
|
||||||
|
VAR B#=2.34567
|
||||||
|
SWAP A%,B#
|
||||||
|
ASSERT__ B#==1, "SWAP"
|
||||||
|
ASSERT__ A%==2, "SWAP"
|
||||||
|
END
|
||||||
|
|
||||||
'REPEAT TEST
|
'REPEAT TEST
|
||||||
?"REPEAT(1)"
|
?"REPEAT(1)"
|
||||||
VAR REPEATTEST
|
VAR REPEATTEST
|
||||||
|
|||||||
@@ -1742,3 +1742,88 @@ class IncRef : Code
|
|||||||
return "incref";
|
return "incref";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SwapCode : Code
|
||||||
|
{
|
||||||
|
void getPointer(ref Value v, out int* ip, out double* dp, out wstring* sp)
|
||||||
|
{
|
||||||
|
ip = null;
|
||||||
|
dp = null;
|
||||||
|
sp = null;
|
||||||
|
if (v.type == ValueType.Reference)
|
||||||
|
{
|
||||||
|
if(v.reference.type == ValueType.Integer)
|
||||||
|
{
|
||||||
|
ip = &v.reference.integerValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(v.reference.type == ValueType.Double)
|
||||||
|
{
|
||||||
|
dp = &v.reference.doubleValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(v.reference.type == ValueType.String)
|
||||||
|
{
|
||||||
|
sp = &v.reference.stringValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (v.type == ValueType.IntegerReference)
|
||||||
|
{
|
||||||
|
ip = v.integerReference;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (v.type == ValueType.DoubleReference)
|
||||||
|
{
|
||||||
|
dp = v.doubleReference;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (v.type == ValueType.StringReference)
|
||||||
|
{
|
||||||
|
sp = v.stringReference;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new TypeMismatch();
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
Value refitem2, refitem1;
|
||||||
|
vm.pop(refitem2);
|
||||||
|
vm.pop(refitem1);
|
||||||
|
double* dp1, dp2;
|
||||||
|
int* ip1, ip2;
|
||||||
|
wstring* sp1, sp2;
|
||||||
|
getPointer(refitem1, ip1, dp1, sp1);
|
||||||
|
getPointer(refitem2, ip2, dp2, sp2);
|
||||||
|
if ((sp1 && (dp2 || ip2)) || (sp2 && (dp1 || ip1)))
|
||||||
|
{
|
||||||
|
throw new TypeMismatch();
|
||||||
|
}
|
||||||
|
import std.algorithm.mutation : swap;
|
||||||
|
if (sp1)
|
||||||
|
{
|
||||||
|
swap(*sp1, *sp2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ip1 && ip2)
|
||||||
|
{
|
||||||
|
swap(*ip1, *ip2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dp1 && dp2)
|
||||||
|
{
|
||||||
|
swap(*dp1, *dp2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double num1 = ip1 ? *ip1 : *dp1;
|
||||||
|
double num2 = ip2 ? *ip2 : *dp2;
|
||||||
|
if (ip2)
|
||||||
|
*ip2 = cast(int)num1;
|
||||||
|
else
|
||||||
|
*dp2 = num1;
|
||||||
|
if (ip1)
|
||||||
|
*ip1 = cast(int)num2;
|
||||||
|
else
|
||||||
|
*dp1 = num2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -886,6 +886,12 @@ class Compiler
|
|||||||
compilePopVar(i, sc);
|
compilePopVar(i, sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void compileSwap(Swap swap, Scope sc)
|
||||||
|
{
|
||||||
|
compilePushReference(swap.item2, sc);
|
||||||
|
compilePushReference(swap.item1, sc);
|
||||||
|
genCode(new SwapCode());
|
||||||
|
}
|
||||||
void compileStatement(Statement i, Scope s)
|
void compileStatement(Statement i, Scope s)
|
||||||
{
|
{
|
||||||
switch(i.type)
|
switch(i.type)
|
||||||
@@ -1132,6 +1138,9 @@ class Compiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NodeType.Swap:
|
||||||
|
compileSwap(cast(Swap)i, s);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
stderr.writeln("Compile:NotImpl ", i.type);
|
stderr.writeln("Compile:NotImpl ", i.type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ enum NodeType
|
|||||||
Input,
|
Input,
|
||||||
RepeatUntil,
|
RepeatUntil,
|
||||||
Option,
|
Option,
|
||||||
|
Swap,
|
||||||
}
|
}
|
||||||
abstract class Node
|
abstract class Node
|
||||||
{
|
{
|
||||||
@@ -590,3 +591,16 @@ class Option : Statement
|
|||||||
argument = arg;
|
argument = arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Swap : Statement
|
||||||
|
{
|
||||||
|
Expression item1;
|
||||||
|
Expression item2;
|
||||||
|
this(Expression item1, Expression item2, SourceLocation loc)
|
||||||
|
{
|
||||||
|
super.location = loc;
|
||||||
|
this.type = NodeType.Swap;
|
||||||
|
this.item1 = item1;
|
||||||
|
this.item2 = item2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ class Lexical
|
|||||||
reserved["ELSEIF"] = TokenType.Elseif;
|
reserved["ELSEIF"] = TokenType.Elseif;
|
||||||
reserved["REPEAT"] = TokenType.Repeat;
|
reserved["REPEAT"] = TokenType.Repeat;
|
||||||
reserved["UNTIL"] = TokenType.Until;
|
reserved["UNTIL"] = TokenType.Until;
|
||||||
|
reserved["SWAP"] = TokenType.Swap;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
}
|
}
|
||||||
this(wstring input)
|
this(wstring input)
|
||||||
@@ -1023,6 +1024,8 @@ class Parser
|
|||||||
writeln("NOTIMPL:EXEC");
|
writeln("NOTIMPL:EXEC");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TokenType.Swap:
|
||||||
|
return swapStatement();
|
||||||
default:
|
default:
|
||||||
syntaxError();
|
syntaxError();
|
||||||
break;
|
break;
|
||||||
@@ -1030,6 +1033,29 @@ class Parser
|
|||||||
lex.popFront();
|
lex.popFront();
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
Swap swapStatement()
|
||||||
|
{
|
||||||
|
lex.popFront();
|
||||||
|
auto expr1 = expression();
|
||||||
|
if (lex.front.type == TokenType.Comma)
|
||||||
|
{
|
||||||
|
lex.popFront();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syntaxError();
|
||||||
|
}
|
||||||
|
auto expr2 = expression();
|
||||||
|
if (!expr1 || !expr2)
|
||||||
|
{
|
||||||
|
syntaxError();
|
||||||
|
}
|
||||||
|
if (!isLValue(expr1) || !isLValue(expr2))
|
||||||
|
{
|
||||||
|
syntaxError();
|
||||||
|
}
|
||||||
|
return new Swap(expr1, expr2, lex.location);
|
||||||
|
}
|
||||||
//左辺値か
|
//左辺値か
|
||||||
bool isLValue(Expression expr)
|
bool isLValue(Expression expr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ enum TokenType
|
|||||||
Elseif,
|
Elseif,
|
||||||
Repeat,
|
Repeat,
|
||||||
Until,
|
Until,
|
||||||
|
Swap,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user