From 9b733cab78b9b475b2244203575f2f4c925dee92 Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Sat, 26 Sep 2015 09:22:46 -0400 Subject: [PATCH] add start to compiler --- compiler/compiler.go | 111 ++++++++++++++++++++++++++++++++++++++++++ compiler/interface.go | 11 +++++ compiler/scope.go | 7 +++ 3 files changed, 129 insertions(+) create mode 100644 compiler/compiler.go create mode 100644 compiler/interface.go create mode 100644 compiler/scope.go diff --git a/compiler/compiler.go b/compiler/compiler.go new file mode 100644 index 0000000..d2464b9 --- /dev/null +++ b/compiler/compiler.go @@ -0,0 +1,111 @@ +package compiler + +import ( + "fmt" + + "github.com/brettlangdon/gython/ast" + "github.com/brettlangdon/gython/bytecode" +) + +type Compiler struct { + nestLevel int + scopeStack []*Scope +} + +func NewCompiler() *Compiler { + return &Compiler{ + nestLevel: 0, + scopeStack: make([]*Scope, 0), + } +} + +func (compiler *Compiler) currentScope() *Scope { + length := len(compiler.scopeStack) + if length > 0 { + return compiler.scopeStack[length-1] + } + return nil +} + +func (compiler *Compiler) enterScope() *Scope { + scope := NewScope() + compiler.scopeStack = append(compiler.scopeStack, scope) + compiler.nestLevel++ + return scope +} + +func (compiler *Compiler) exitScope() *Scope { + last := len(compiler.scopeStack) - 1 + scope := compiler.scopeStack[last] + compiler.scopeStack = compiler.scopeStack[:last] + compiler.nestLevel-- + return scope +} + +func (compiler *Compiler) assemble(addNone bool) *bytecode.CodeObject { + if addNone { + compiler.addOp(bytecode.LOAD_CONST) + compiler.addOp(bytecode.RETURN_VALUE) + } + + codeobject := bytecode.NewCodeObject() + return codeobject +} + +func (compiler *Compiler) addOp(op bytecode.Opcode) bool { + fmt.Println(bytecode.Opnames[op]) + return true +} + +func (compiler *Compiler) visitExpression(expr ast.Expression) bool { + switch expr := expr.(type) { + case *ast.Num: + compiler.addOp(bytecode.LOAD_CONST) + case *ast.Name: + compiler.addOp(bytecode.STORE_NAME) + default: + fmt.Println(expr) + } + + return true +} + +func (compiler *Compiler) visitStatement(stmt ast.Statement) bool { + switch stmt := stmt.(type) { + case *ast.Assign: + compiler.visitExpression(stmt.Value) + length := len(stmt.Targets) + for i := 0; i < length; i++ { + if i < length-1 { + compiler.addOp(bytecode.DUP_TOP) + } + compiler.visitExpression(stmt.Targets[i]) + } + } + return true +} + +func (compiler *Compiler) compileBody(stmts []ast.Statement) bool { + // TODO: Check for docstring + for _, stmt := range stmts { + compiler.visitStatement(stmt) + } + return true +} + +func (compiler *Compiler) CompileMod(root ast.Mod) *bytecode.CodeObject { + addNone := true + compiler.enterScope() + var codeobject *bytecode.CodeObject + switch root := root.(type) { + case *ast.Module: + if !compiler.compileBody(root.Body) { + compiler.exitScope() + return nil + } + } + + codeobject = compiler.assemble(addNone) + compiler.exitScope() + return codeobject +} diff --git a/compiler/interface.go b/compiler/interface.go new file mode 100644 index 0000000..46a9cab --- /dev/null +++ b/compiler/interface.go @@ -0,0 +1,11 @@ +package compiler + +import ( + "github.com/brettlangdon/gython/ast" + "github.com/brettlangdon/gython/bytecode" +) + +func CompileAST(root ast.Mod) *bytecode.CodeObject { + compiler := NewCompiler() + return compiler.CompileMod(root) +} diff --git a/compiler/scope.go b/compiler/scope.go new file mode 100644 index 0000000..13a2415 --- /dev/null +++ b/compiler/scope.go @@ -0,0 +1,7 @@ +package compiler + +type Scope struct{} + +func NewScope() *Scope { + return &Scope{} +}