From 20889c28e1b5817adb8794c30b28ccb50cc45305 Mon Sep 17 00:00:00 2001 From: otya128 Date: Thu, 29 Dec 2016 17:59:47 +0900 Subject: [PATCH] Implement LINPUT --- SMILEBASIC/VM.d | 10 ++++++++++ SMILEBASIC/compiler.d | 12 ++++++++++++ SMILEBASIC/node.d | 22 ++++++++++++++++++++++ SMILEBASIC/parser.d | 35 +++++++++++++++++++++++++++++++++++ SMILEBASIC/token.d | 1 + 5 files changed, 80 insertions(+) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 3aa7e27..f031ffb 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -2551,3 +2551,13 @@ class GosubUndefinedLabel : Code throw new UndefinedLabel(label); } } + +class Linput : Code +{ + override void execute(VM vm) + { + Value guide; + vm.pop(guide); + vm.push(Value(vm.petitcomputer.input(guide.castDString, false))); + } +} diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 478a016..aead1dd 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -941,6 +941,15 @@ class Compiler compileExpression(use.expression, sc); genCode(new otya.smilebasic.vm.Use); } + void compileLinput(otya.smilebasic.node.Linput linput, Scope sc) + { + if (linput.hasGuide) + compileExpression(linput.guide, sc); + else + genCodeImm(Value("")); + genCode(new otya.smilebasic.vm.Linput); + compilePopVar(linput.expression, sc); + } void compileStatement(Statement i, Scope s) { switch(i.type) @@ -1215,6 +1224,9 @@ class Compiler case NodeType.Use: compileUse(cast(otya.smilebasic.node.Use)i, s); break; + case NodeType.Linput: + compileLinput(cast(otya.smilebasic.node.Linput)i, s); + break; default: stderr.writeln("Compile:NotImpl ", i.type); } diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index bce53f4..fe2b460 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -50,6 +50,7 @@ enum NodeType XOff, Exec, Use, + Linput, } abstract class Node { @@ -675,3 +676,24 @@ class Use : Statement this.type = NodeType.Use; } } +class Linput : Statement +{ + bool hasGuide; + Expression guide; + Expression expression; + this(Expression guide, Expression expr, SourceLocation loc) + { + super.location = loc; + this.type = NodeType.Linput; + this.hasGuide = true; + this.guide = guide; + this.expression = expr; + } + this(Expression expr, SourceLocation loc) + { + super.location = loc; + this.type = NodeType.Linput; + this.hasGuide = false; + this.expression = expr; + } +} diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 8211609..6ad85a7 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -82,6 +82,7 @@ class Lexical reserved["REPEAT"] = TokenType.Repeat; reserved["UNTIL"] = TokenType.Until; reserved["SWAP"] = TokenType.Swap; + reserved["LINPUT"] = TokenType.Linput; reserved.rehash(); } this(wstring input) @@ -1124,6 +1125,8 @@ class Parser break; case TokenType.Swap: return swapStatement(); + case TokenType.Linput: + return linputStatement(); default: syntaxError(); break; @@ -1131,6 +1134,38 @@ class Parser lex.popFront(); return node; } + Linput linputStatement() + { + auto location = lex.location; + lex.popFront(); + Expression message = expression(); + if(!message) + { + syntaxError(); + return null; + } + auto token = lex.front(); + if (token.type == TokenType.Semicolon) + { + lex.popFront(); + Expression var = expression(); + if (!isLValue(var)) + { + syntaxError(); + return null; + } + return new Linput(message, var, location); + } + else + { + if (!isLValue(message)) + { + syntaxError(); + return null; + } + return new Linput(message, location); + } + } Swap swapStatement() { lex.popFront(); diff --git a/SMILEBASIC/token.d b/SMILEBASIC/token.d index 306ff77..8ad5bcb 100644 --- a/SMILEBASIC/token.d +++ b/SMILEBASIC/token.d @@ -76,6 +76,7 @@ enum TokenType Swap, Dim, Constant, + Linput, } enum TokenValueType