Implement LINPUT
This commit is contained in:
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -76,6 +76,7 @@ enum TokenType
|
||||
Swap,
|
||||
Dim,
|
||||
Constant,
|
||||
Linput,
|
||||
}
|
||||
|
||||
enum TokenValueType
|
||||
|
||||
Reference in New Issue
Block a user