From 6505e41fd2edb7d7c344f169d1721e562d53327f Mon Sep 17 00:00:00 2001 From: otya128 Date: Sat, 3 Sep 2016 11:46:11 +0900 Subject: [PATCH] =?UTF-8?q?SWAP=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SMILEBASIC/TEST.txt | 20 ++++++++++ SMILEBASIC/VM.d | 85 +++++++++++++++++++++++++++++++++++++++++++ SMILEBASIC/compiler.d | 9 +++++ SMILEBASIC/node.d | 14 +++++++ SMILEBASIC/parser.d | 26 +++++++++++++ SMILEBASIC/token.d | 1 + 6 files changed, 155 insertions(+) diff --git a/SMILEBASIC/TEST.txt b/SMILEBASIC/TEST.txt index ad456d1..268f4c8 100644 --- a/SMILEBASIC/TEST.txt +++ b/SMILEBASIC/TEST.txt @@ -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 diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 1272e1d..0802dae 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -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; + } +} diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index b3f38f8..2fa39e6 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -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); } diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index 9169a19..6205364 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -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; + } +} diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index df35d3f..63be547 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -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) { diff --git a/SMILEBASIC/token.d b/SMILEBASIC/token.d index 4500d8f..79df08e 100644 --- a/SMILEBASIC/token.d +++ b/SMILEBASIC/token.d @@ -72,6 +72,7 @@ enum TokenType Elseif, Repeat, Until, + Swap, } struct Token