Browse Source

add start to compiler

master
Brett Langdon 10 years ago
parent
commit
9b733cab78
3 changed files with 129 additions and 0 deletions
  1. +111
    -0
      compiler/compiler.go
  2. +11
    -0
      compiler/interface.go
  3. +7
    -0
      compiler/scope.go

+ 111
- 0
compiler/compiler.go View File

@ -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
}

+ 11
- 0
compiler/interface.go View File

@ -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)
}

+ 7
- 0
compiler/scope.go View File

@ -0,0 +1,7 @@
package compiler
type Scope struct{}
func NewScope() *Scope {
return &Scope{}
}

Loading…
Cancel
Save