export type Literal struct {
+ pos_ int;
typ_ *Globals.Type;
b bool;
i int;
}
+func (x *Literal) pos() int {
+ return x.pos_;
+}
+
+
func (x *Literal) typ() *Globals.Type {
return x.typ_;
}
-export func NewLiteral(typ *Globals.Type) *Literal {
+export func NewLiteral(pos int, typ *Globals.Type) *Literal {
x := new(Literal);
+ x.pos_ = pos;
x.typ_ = typ;
return x;
}
// method to its interface. However, this would require renaming the
// typ field everywhere... - Need to think about accessors again.
export type Object struct {
+ pos_ int;
obj *Globals.Object;
}
+func (x *Object) pos() int {
+ return x.pos_;
+}
+
+
func (x *Object) typ() *Globals.Type {
return x.obj.typ;
}
-export func NewObject(obj* Globals.Object) *Object {
+export func NewObject(pos int, obj* Globals.Object) *Object {
x := new(Object);
+ x.pos_ = pos;
x.obj = obj;
return x;
}
+// TODO model Selector as binary operation?
export type Selector struct {
+ pos_ int;
typ_ *Globals.Type;
}
+func (x *Selector) pos() int {
+ return x.pos_;
+}
+
+
func (x *Selector) typ() *Globals.Type {
return x.typ_;
}
+export func NewSelector(pos int, typ *Globals.Type) *Selector {
+ x := new(Selector);
+ x.pos_ = pos;
+ x.typ_ = typ;
+ return x;
+}
+
+
export type BinaryExpr struct {
+ pos_ int;
typ_ *Globals.Type;
op int;
x, y Globals.Expr;
}
+func (x *BinaryExpr) pos() int {
+ return x.pos_;
+}
+
+
func (x *BinaryExpr) typ() *Globals.Type {
return x.typ_;
}
// Initialization
func init() {
- Bad = NewLiteral(Universe.bad_t);
- True = NewLiteral(Universe.bool_t); True.b = true;
- False = NewLiteral(Universe.bool_t); False.b = false;
- Nil = NewLiteral(Universe.nil_t);
+ Bad = NewLiteral(-1, Universe.bad_t);
+ True = NewLiteral(-1, Universe.bool_t); True.b = true;
+ False = NewLiteral(-1, Universe.bool_t); False.b = false;
+ Nil = NewLiteral(-1, Universe.nil_t);
}
// ----------------------------------------------------------------------------
// Expressions
-func (P *Parser) ParseExpressionList() *Globals.List {
+func (P *Parser) ParseExpressionList(list *Globals.List) {
P.Trace("ExpressionList");
- list := Globals.NewList();
list.AddExpr(P.ParseExpression());
for P.tok == Scanner.COMMA {
P.Next();
list.AddExpr(P.ParseExpression());
}
+ P.Ecart();
+}
+
+
+func (P *Parser) ParseNewExpressionList() *Globals.List {
+ P.Trace("NewExpressionList");
+
+ list := Globals.NewList();
+ P.ParseExpressionList(list);
+
P.Ecart();
return list;
}
P.Expect(Scanner.NEW);
P.Expect(Scanner.LPAREN);
P.ParseType();
+ args := Globals.NewList();
if P.tok == Scanner.COMMA {
P.Next();
- P.ParseExpressionList()
+ P.ParseExpressionList(args)
}
P.Expect(Scanner.RPAREN);
}
-func (P *Parser) ParseSingleExpressionList(list *Globals.List) {
- P.Trace("SingleExpressionList");
-
- list.AddExpr(P.ParseExpression());
- for P.tok == Scanner.COMMA {
- P.Next();
- list.AddExpr(P.ParseExpression());
- }
-
- P.Ecart();
-}
-
-
func (P *Parser) ParseExpressionPair(list *Globals.List) {
P.Trace("ExpressionPair");
func (P *Parser) ParseBuiltinCall() Globals.Expr {
P.Trace("BuiltinCall");
- P.ParseExpressionList(); // TODO should be optional
+ args := Globals.NewList();
+ P.ParseExpressionList(args); // TODO should be optional
P.Ecart();
return nil;
if P.tok == Scanner.COMMA {
P.Next();
if P.tok != paren {
- P.ParseSingleExpressionList(list);
+ P.ParseExpressionList(list);
}
} else if P.tok == Scanner.COLON {
P.Next();
if obj.kind == Object.TYPE {
res = P.ParseCompositeLit(obj.typ);
} else {
- res = AST.NewObject(obj);
+ res = AST.NewObject(pos, obj);
}
}
}
P.Expect(Scanner.RPAREN);
case Scanner.INT:
- x := AST.NewLiteral(Universe.int_t);
+ x := AST.NewLiteral(P.pos, Universe.int_t);
x.i = 42; // TODO set the right value
res = x;
P.Next();
case Scanner.FLOAT:
- x := AST.NewLiteral(Universe.float_t);
+ x := AST.NewLiteral(P.pos, Universe.float_t);
x.f = 42.0; // TODO set the right value
res = x;
P.Next();
case Scanner.STRING:
- x := AST.NewLiteral(Universe.string_t);
+ x := AST.NewLiteral(P.pos, Universe.string_t);
x.s = P.val; // TODO need to strip quotes, interpret string properly
res = x;
P.Next();
res = AST.Nil;
case Scanner.IOTA:
- x := AST.NewLiteral(Universe.int_t);
+ x := AST.NewLiteral(P.pos, Universe.int_t);
x.i = 42; // TODO set the right value
res = x;
P.Next();
func (P *Parser) ParseSelectorOrTypeAssertion(x Globals.Expr) Globals.Expr {
P.Trace("SelectorOrTypeAssertion");
- pos := P.pos;
+ period_pos := P.pos;
P.Expect(Scanner.PERIOD);
- if P.semantic_checks {
- typ := x.typ();
- if typ.form != Type.STRUCT || typ.form != Type.INTERFACE {
- P.Error(pos, `"." cannot be applied to this operand`);
- }
- }
if P.tok == Scanner.IDENT {
+ ident_pos := P.pos;
ident := P.ParseIdent();
+ if P.semantic_checks {
+ switch typ := x.typ(); typ.form {
+ case Type.BAD:
+ // ignore
+ break;
+ case Type.STRUCT, Type.INTERFACE:
+ obj := typ.scope.Lookup(ident);
+ if obj != nil {
+ x = AST.NewSelector(x.pos(), obj.typ);
+
+ } else {
+ P.Error(ident_pos, `no field/method "` + ident + `"`);
+ x = AST.Bad;
+ }
+ default:
+ P.Error(period_pos, `"." not applicable`);
+ x = AST.Bad;
+ }
+ }
+
} else {
P.Expect(Scanner.LPAREN);
P.ParseType();
P.Expect(Scanner.RPAREN);
+
+ if P.semantic_checks {
+ panic "UNIMPLEMENTED";
+ }
}
P.Ecart();
func (P *Parser) ParseIndexOrSlice(x Globals.Expr) Globals.Expr {
P.Trace("IndexOrSlice");
+ pos := P.pos;
P.Expect(Scanner.LBRACK);
- P.ParseExpression();
+ i1 := P.ParseExpression();
+ var i2 Globals.Expr;
if P.tok == Scanner.COLON {
P.Next();
- P.ParseExpression();
+ i2 := P.ParseExpression();
}
P.Expect(Scanner.RBRACK);
+ if P.semantic_checks {
+ switch typ := x.typ(); typ.form {
+ case Type.BAD:
+ // ignore
+ break;
+ case Type.STRING, Type.ARRAY:
+ panic "UNIMPLEMENTED";
+
+ case Type.MAP:
+ if Type.Equal(typ.aux, i1.typ()) {
+ // x = AST.NewSubscript(x, i1);
+ panic "UNIMPLEMENTED";
+
+ } else {
+ P.Error(x.pos(), "map key type mismatch");
+ x = AST.Bad;
+ }
+
+ default:
+ P.Error(pos, `"[]" not applicable`);
+ x = AST.Bad;
+ }
+
+ }
+
P.Ecart();
return x;
}
func (P *Parser) ParseCall(x Globals.Expr) Globals.Expr {
P.Trace("Call");
-
+
P.Expect(Scanner.LPAREN);
+ args := Globals.NewList();
if P.tok != Scanner.RPAREN {
- P.ParseExpressionList();
+ P.ParseExpressionList(args);
}
P.Expect(Scanner.RPAREN);
+
+ if P.semantic_checks {
+ panic "UNIMPLEMENTED";
+ }
P.Ecart();
return x;
}
-func (P *Parser) ParsePrimaryExprList() {
+// TODO is this function needed?
+func (P *Parser) ParsePrimaryExprList() *Globals.List {
P.Trace("PrimaryExprList");
-
- P.ParsePrimaryExpr(-1, "");
+
+ list := Globals.NewList();
+ list.AddExpr(P.ParsePrimaryExpr(-1, ""));
for P.tok == Scanner.COMMA {
P.Next();
- P.ParsePrimaryExpr(-1, "");
+ list.AddExpr(P.ParsePrimaryExpr(-1, ""));
}
P.Ecart();
+ return list;
}
}
P.Next();
pos := P.pos;
- val_list := P.ParseExpressionList();
+ val_list := P.ParseNewExpressionList();
if P.semantic_checks && val_list.len_ != ident_list.len_ {
P.Error(pos, "number of expressions does not match number of variables");
}
P.ConvertToExprList(pos_list, ident_list, expr_list);
P.Next();
pos := P.pos;
- val_list := P.ParseExpressionList();
+ val_list := P.ParseNewExpressionList();
if P.semantic_checks && val_list.len_ != expr_list.len_ {
P.Error(pos, "number of expressions does not match number of variables");
}
P.Trace("ReturnStat");
P.Expect(Scanner.RETURN);
+ res := Globals.NewList();
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
- P.ParseExpressionList();
+ P.ParseExpressionList(res);
}
P.Ecart();
if P.tok == Scanner.CASE {
P.Next();
- P.ParseExpressionList();
+ list := Globals.NewList();
+ P.ParseExpressionList(list);
} else {
P.Expect(Scanner.DEFAULT);
}
if P.tok == Scanner.ASSIGN {
P.Next();
- P.ParseExpressionList();
+ P.ParseNewExpressionList();
}
if exported {
list := P.ParseIdentDeclList(Object.VAR);
if P.tok == Scanner.ASSIGN {
P.Next();
- P.ParseExpressionList();
+ P.ParseNewExpressionList();
} else {
typ := P.ParseVarType();
for p := list.first; p != nil; p = p.next {
}
if P.tok == Scanner.ASSIGN {
P.Next();
- P.ParseExpressionList();
+ P.ParseNewExpressionList();
}
}