From: Michael D. Lowis Date: Sun, 19 Apr 2020 18:47:22 +0000 (-0400) Subject: checkpoint commit before breaking out codegen stuff X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=101e380b87d3eb6165495d475a16aebb2a3493e6;p=proto%2Fsclpl-rb.git checkpoint commit before breaking out codegen stuff --- diff --git a/dyn.src b/dyn.src index d873699..58983d8 100644 --- a/dyn.src +++ b/dyn.src @@ -28,3 +28,7 @@ #print(1,2,3,4,5,6,7,8,9) #(-1) #(+1) + +let foo = fun(a) + println("hi!") +end diff --git a/dyn2.rb b/dyn2.rb index 3b70fdc..aeb2d54 100755 --- a/dyn2.rb +++ b/dyn2.rb @@ -86,6 +86,60 @@ class Lexer end end +class Codegen + def initialize() + @protos = StringIO.new + @funcs = {} + @func_stack = [] + @func_id = 0 + @temp_id = 0 + end + + +# def emit_line(str) +# @func_stack.last.puts str +# end +# +# def emit(str) +# @func_stack.last.print str +# end +# +# def emit_expr(expr) +# v = get_tempvar() +# emit_line " Value #{v} = #{expr};" +# v +# end +# +# def dump(file=$stdout) +# file.puts @protos.string +# @funcs.each {|f| file.puts f.string } +# end +# +# def func_start() +# io = StringIO.new +# @syms.scope_start +# @funcs.push(io) +# @func_stack.push(io) +# end +# +# def func_stop +# @syms.scope_stop() +# @func_stack.pop() +# end + + private + + def mkfunc() + @func_id += 1 + "__anonfunc#{@func_id}" + end + + def mkvar() + @temp_id += 1 + "__tmp#{@temp_id}" + end +end + class Parser LEVELS = { none: 0, @@ -136,25 +190,6 @@ class Parser @func_id = 0 end - def toplevel() - func_start() - emit_line "Value toplevel(void) {" - expr = emit_expr "NULL" - while !matches(:eof) - expr = expression() - end - emit_line " return #{expr};" - emit_line "}" - func_stop() - end - - ####################################### - # Expression Parsing - ####################################### - def expression() - parseLevel(:assign) - end - def getRule(tok) RULES[tok.type] || {} end @@ -188,6 +223,65 @@ class Parser LVLNAMES[index + 1] end + def error(str) + puts "#{@lex.file}:#{@lex.linenum(@next || @prev)}: #{str}" + exit 1 + end + + def peek() + @next = @lex.next if @next.nil? + @next + end + + def matches(type) + (peek().type == type) + end + + def accept(type) + if (matches(type)) + @prev = @next + @next = nil + true + else + false + end + end + + def expect(type) + tok = peek() + if not accept(type) + error("expected '#{type}', received '#{tok.type}'") + end + tok + end + + def consume() + expect(peek().type) + end + + def eof? + (peek().type == :eof) + end + + def toplevel() + func_start() + emit_line "Value toplevel(void) {" + expr = emit_expr "NULL" + while !matches(:eof) + expr = expression() + end + emit_line " return #{expr};" + emit_line "}" + func_stop() + end + + ####################################### + # Expression Parsing + ####################################### + def expression() + parseLevel(:assign) + end + def assign(left) if (left.to_s.start_with? "__tmp") error("invalid expression on left-hand side of assignment") @@ -389,49 +483,6 @@ class Parser @syms.scope_stop() @func_stack.pop() end - - ####################################### - # Parsing Primitives - ####################################### - def error(str) - puts "#{@lex.file}:#{@lex.linenum(@next || @prev)}: #{str}" - exit 1 - end - - def peek() - @next = @lex.next if @next.nil? - @next - end - - def matches(type) - (peek().type == type) - end - - def accept(type) - if (matches(type)) - @prev = @next - @next = nil - true - else - false - end - end - - def expect(type) - tok = peek() - if not accept(type) - error("expected '#{type}', received '#{tok.type}'") - end - tok - end - - def consume() - expect(peek().type) - end - - def eof? - (peek().type == :eof) - end end parse = Parser.new("dyn.src")