summaryrefslogtreecommitdiff
path: root/usr/austin/eval/stmt.go
diff options
context:
space:
mode:
Diffstat (limited to 'usr/austin/eval/stmt.go')
-rw-r--r--usr/austin/eval/stmt.go140
1 files changed, 70 insertions, 70 deletions
diff --git a/usr/austin/eval/stmt.go b/usr/austin/eval/stmt.go
index a3573c260..9788bb09c 100644
--- a/usr/austin/eval/stmt.go
+++ b/usr/austin/eval/stmt.go
@@ -341,36 +341,12 @@ func (a *stmtCompiler) compileDeclStmt(s *ast.DeclStmt) {
switch decl.Tok {
case token.IMPORT:
log.Crash("import at statement level");
-
case token.CONST:
log.Crashf("%v not implemented", decl.Tok);
-
case token.TYPE:
a.compileTypeDecl(a.block, decl);
-
case token.VAR:
- for _, spec := range decl.Specs {
- spec := spec.(*ast.ValueSpec);
- if spec.Values == nil {
- // Declaration without assignment
- if spec.Type == nil {
- // Parser should have caught
- log.Crash("Type and Values nil");
- }
- t := a.compileType(a.block, spec.Type);
- // Define placeholders even if type compile failed
- for _, n := range spec.Names {
- a.defineVar(n, t);
- }
- } else {
- // Decalaration with assignment
- lhs := make([]ast.Expr, len(spec.Names));
- for i, n := range spec.Names {
- lhs[i] = n;
- }
- a.doAssign(lhs, spec.Values, decl.Tok, spec.Type);
- }
- }
+ a.compileVarDecl(decl);
}
default:
@@ -378,6 +354,73 @@ func (a *stmtCompiler) compileDeclStmt(s *ast.DeclStmt) {
}
}
+// decl might or might not be at top level;
+func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) {
+ for _, spec := range decl.Specs {
+ spec := spec.(*ast.ValueSpec);
+ if spec.Values == nil {
+ // Declaration without assignment
+ if spec.Type == nil {
+ // Parser should have caught
+ log.Crash("Type and Values nil");
+ }
+ t := a.compileType(a.block, spec.Type);
+ // Define placeholders even if type compile failed
+ for _, n := range spec.Names {
+ a.defineVar(n, t);
+ }
+ } else {
+ // Decalaration with assignment
+ lhs := make([]ast.Expr, len(spec.Names));
+ for i, n := range spec.Names {
+ lhs[i] = n;
+ }
+ a.doAssign(lhs, spec.Values, decl.Tok, spec.Type);
+ }
+ }
+}
+
+// decl is top level
+func (a *stmtCompiler) compileDecl(decl ast.Decl) {
+ switch d := decl.(type) {
+ case *ast.BadDecl:
+ // Do nothing. Already reported by parser.
+ a.silentErrors++;
+
+ case *ast.FuncDecl:
+ decl := a.compileFuncType(a.block, d.Type);
+ if decl == nil {
+ return;
+ }
+ // Declare and initialize v before compiling func
+ // so that body can refer to itself.
+ c := a.block.DefineConst(d.Name.Value, a.pos, decl.Type, decl.Type.Zero());
+ // TODO(rsc): How to mark v as constant
+ // so the type checker rejects assignments to it?
+ fn := a.compileFunc(a.block, decl, d.Body);
+ if fn == nil {
+ return;
+ }
+ var zeroThread Thread;
+ c.Value.(FuncValue).Set(fn(&zeroThread));
+
+ case *ast.GenDecl:
+ switch d.Tok {
+ case token.IMPORT:
+ log.Crashf("%v not implemented", d.Tok);
+ case token.CONST:
+ log.Crashf("%v not implemented", d.Tok);
+ case token.TYPE:
+ a.compileTypeDecl(a.block, d);
+ case token.VAR:
+ a.compileVarDecl(d);
+ }
+
+ default:
+ log.Crashf("Unexpected Decl type %T", decl);
+ }
+}
+
func (a *stmtCompiler) compileLabeledStmt(s *ast.LabeledStmt) {
// Define label
l, ok := a.labels[s.Label.Value];
@@ -1205,14 +1248,14 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f
if decl.InNames[i] != nil {
bodyScope.DefineVar(decl.InNames[i].Value, decl.InNames[i].Pos(), t);
} else {
- bodyScope.DefineSlot(t);
+ bodyScope.DefineTemp(t);
}
}
for i, t := range decl.Type.Out {
if decl.OutNames[i] != nil {
bodyScope.DefineVar(decl.OutNames[i].Value, decl.OutNames[i].Pos(), t);
} else {
- bodyScope.DefineSlot(t);
+ bodyScope.DefineTemp(t);
}
}
@@ -1271,46 +1314,3 @@ func (a *funcCompiler) checkLabels() {
// point of the goto.
a.flow.gotosObeyScopes(a.compiler);
}
-
-/*
- * Public interface
- */
-
-type Stmt struct {
- code code;
-}
-
-func (s *Stmt) Exec(f *Frame) os.Error {
- t := new(Thread);
- t.f = f;
- return t.Try(func(t *Thread){s.code.exec(t)});
-}
-
-func CompileStmts(scope *Scope, stmts []ast.Stmt) (*Stmt, os.Error) {
- errors := scanner.NewErrorVector();
- cc := &compiler{errors, 0, 0};
- cb := newCodeBuf();
- fc := &funcCompiler{
- compiler: cc,
- fnType: nil,
- outVarsNamed: false,
- codeBuf: cb,
- flow: newFlowBuf(cb),
- labels: make(map[string] *label),
- };
- bc := &blockCompiler{
- funcCompiler: fc,
- block: scope.block,
- };
- out := make([]*Stmt, len(stmts));
- nerr := cc.numError();
- for i, stmt := range stmts {
- bc.compileStmt(stmt);
- }
- fc.checkLabels();
- if nerr != cc.numError() {
- return nil, errors.GetError(scanner.Sorted);
- }
- code := fc.get();
- return &Stmt{code}, nil;
-}