From c33df7e4ac80c7dd9d19711f122f5daf5bb15ed6 Mon Sep 17 00:00:00 2001 From: otya128 Date: Thu, 4 Jun 2015 22:53:15 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=B3=E3=83=B3=E3=83=91=E3=82=A4=E3=83=AB?= =?UTF-8?q?=E3=81=97=E3=81=A6=E5=AE=9F=E8=A1=8C=E3=81=A7=E3=81=8D=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SMILEBASIC/VM.d | 88 +++++++++++++++++++++++++++++++++++++++++-- SMILEBASIC/compiler.d | 73 ++++++++++++++++++++++++++++++++++- SMILEBASIC/main.d | 6 +-- SMILEBASIC/parser.d | 32 +++++++++------- SMILEBASIC/type.d | 11 ++++++ 5 files changed, 187 insertions(+), 23 deletions(-) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 3107dee..18b44fa 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -1,32 +1,112 @@ module otya.smilebasic.vm; +import otya.smilebasic.type; +import otya.smilebasic.token; +import std.uni; +import std.conv; +import std.stdio; class VM { + Code[] code; + int stacki; + Value[] stack; + this(Code[] code) + { + this.code = code; + this.stack = new Value[1024 * 1024]; + } + void run() + { + for(int i = 0; i < this.code.length; i++) + { + code[i].execute(this); + } + } + void push(ref Value value) + { + stack[stacki++] = value; + } + void pop(out Value value) + { + value = stack[--stacki]; + } } enum CodeType { - PushI, - PushD, - PushS, + Push, Operate, Return, Goto, Gosub, + Print, } abstract class Code { CodeType type; abstract void execute(VM vm); } +class PrintCode : Code +{ + int count; + this(int count) + { + this.type = CodeType.Print; + this.count = count; + } + override void execute(VM vm) + { + for(int i = 0;i < count; i++) + { + Value arg; + vm.pop(arg); + switch(arg.type) + { + case ValueType.Integer: + write(arg.integerValue); + break; + case ValueType.String: + write(cast(string)arg.stringValue); + break; + default: + //type missmatch + break; + } + } + } +} /* * スタックにPush */ class Push : Code { - + Value imm; + this(Value imm) + { + this.type = CodeType.Push; + this.imm = imm; + } + override void execute(VM vm) + { + vm.push(imm); + } } class Operate : Code { + TokenType operator; + this(TokenType op) + { + this.operator = op; + } + override void execute(VM vm) + { + Value l; + Value r; + vm.pop(l); + vm.pop(r); + //とりあえずInteger + l.integerValue += r.integerValue; + vm.push(l); + } } class Goto : Code { diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 0051ac0..cb62827 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -1,6 +1,8 @@ module otya.smilebasic.compiler; import otya.smilebasic.node; +import otya.smilebasic.token; import otya.smilebasic.vm; +import otya.smilebasic.type; import std.stdio; class Compiler { @@ -8,18 +10,85 @@ class Compiler this(Statements statements) { this.statements = statements; + code = new Code[0]; } - void compile() + Code[] code; + void genCodeImm(Value value) + { + code ~= new Push(value); + } + void genCodeOP(TokenType op) + { + code ~= new Operate(op); + } + void compileExpression(Expression exp) + { + + switch(exp.type) + { + case NodeType.Constant: + genCodeImm((cast(Constant)exp).value); + break; + case NodeType.BinaryOperator: + { + auto binop = cast(BinaryOperator)exp; + compileExpression(binop.item1); + compileExpression(binop.item2); + genCodeOP(binop.operator); + } + break; + case NodeType.Variable: + break; + case NodeType.CallFunction: + { + auto func = cast(CallFunction)exp; + if(func.name == "ADD") + { + foreach_reverse(Expression i ; func.args) + { + compileExpression(i); + } + } + } + break; + default: + break; + } + } + VM compile() { - Code[] code = new Code[0]; foreach(Statement i ; statements.statements) { switch(i.type) { + case NodeType.Print: + { + auto print = cast(Print)i; + foreach_reverse(PrintArgument j ; print.args) + { + switch(j.type) + { + case PrintArgumentType.Expression: + compileExpression(j.expression); + break; + case PrintArgumentType.Line: + genCodeImm(Value("\n")); + break; + case PrintArgumentType.Tab: + genCodeImm(Value("\t")); + break; + default: + break; + } + } + code ~= new PrintCode(print.args.length); + } + break; default: stderr.writeln("Compile:NotImpl ", i.type); } } + return new VM(code); } } diff --git a/SMILEBASIC/main.d b/SMILEBASIC/main.d index 11088eb..43ad17b 100644 --- a/SMILEBASIC/main.d +++ b/SMILEBASIC/main.d @@ -2,15 +2,15 @@ import std.stdio; import otya.smilebasic.parser; int main(string[] argv) { - writeln("Hello D-World!"); version(none) { auto parser = new Parser("ADD(ADD(1,2,3,4,5,6),2,3,4,5,6)"); writeln(parser.calc()); } - auto parser = new Parser("PRINT 1+1"); - parser.compile(); + auto parser = new Parser("PRINT 1+1,2+3;10-5"); + auto vm = parser.compile(); + vm.run(); readln(); return 0; } diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index ab15f0e..a315c6e 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -260,10 +260,10 @@ class Parser return - - -1; } } - void compile() + auto compile() { auto compiler = new Compiler(parseProgram()); - compiler.compile(); + return compiler.compile(); } Statements parseProgram() { @@ -305,17 +305,6 @@ class Parser print.addLine(); break; } - if(token.type == TokenType.Semicolon) - { - addline = false; - continue; - } - if(token.type == TokenType.Comma) - { - print.addTab(); - addline = false; - continue; - } addline = true; auto exp = expression(); if(exp is null) @@ -324,13 +313,28 @@ class Parser continue; } print.addArgument(exp); - lex.popFront(); token = lex.front(); if(lex.empty()) break; if(token.type != TokenType.Colon && token.type != TokenType.NewLine && token.type != TokenType.Semicolon && token.type != TokenType.Comma) { syntaxError(); } + else + { + lex.popFront(); + if(token.type == TokenType.Semicolon) + { + addline = false; + continue; + } + if(token.type == TokenType.Comma) + { + print.addTab(); + addline = false; + continue; + } + token = lex.front(); + } } return print; } diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index a28e768..5e374a2 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -34,4 +34,15 @@ struct Value this.type = ValueType.String; stringValue = value; } + void castOp(ValueType type) + { + switch(type) + { + case ValueType.Double: + + break; + default: + break; + } + } }