1
0

SWAPを実装

This commit is contained in:
otya128
2016-09-03 11:46:11 +09:00
parent 69a4033250
commit 6505e41fd2
6 changed files with 155 additions and 0 deletions

View File

@@ -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(1)"
VAR REPEATTEST

View File

@@ -1742,3 +1742,88 @@ class IncRef : Code
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;
}
}

View File

@@ -886,6 +886,12 @@ class Compiler
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)
{
switch(i.type)
@@ -1132,6 +1138,9 @@ class Compiler
}
}
break;
case NodeType.Swap:
compileSwap(cast(Swap)i, s);
break;
default:
stderr.writeln("Compile:NotImpl ", i.type);
}

View File

@@ -43,6 +43,7 @@ enum NodeType
Input,
RepeatUntil,
Option,
Swap,
}
abstract class Node
{
@@ -590,3 +591,16 @@ class Option : Statement
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;
}
}

View File

@@ -81,6 +81,7 @@ class Lexical
reserved["ELSEIF"] = TokenType.Elseif;
reserved["REPEAT"] = TokenType.Repeat;
reserved["UNTIL"] = TokenType.Until;
reserved["SWAP"] = TokenType.Swap;
reserved.rehash();
}
this(wstring input)
@@ -1023,6 +1024,8 @@ class Parser
writeln("NOTIMPL:EXEC");
}
break;
case TokenType.Swap:
return swapStatement();
default:
syntaxError();
break;
@@ -1030,6 +1033,29 @@ class Parser
lex.popFront();
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)
{

View File

@@ -72,6 +72,7 @@ enum TokenType
Elseif,
Repeat,
Until,
Swap,
}
struct Token