| |
---|
| | private def analyzeClass(tree: ClassDef): Unit = tree match { |
---|
| | case ClassDef(name, None, members) => |
---|
| | classScope.get(name.name) match { |
---|
| | case Some(c) => |
---|
| | Report.error(tree.pos, "Class already defined: " + name.name) |
---|
| | Report.error(tree.pos, "Class already defined: " + name) |
---|
| | case None => |
---|
| | val cs = ClassSymbol(tree.pos, name.name, None); |
---|
| | classScope(name.name) = cs; |
---|
| | members.foreach(x => analyzeMember(cs,x)) |
---|
| | } |
---|
| | case ClassDef(name, extend, members) => |
---|
| | classScope.get(name.name) match { |
---|
| | case Some(c) => |
---|
| | Report.error(tree.pos, "Class already defined: " + name.name); |
---|
| | Report.error(tree.pos, "Class already defined: " + name); |
---|
| | case None => |
---|
| | val cs = ClassSymbol(tree.pos, name.name, classScope.get(extend.get.name)); |
---|
| | classScope(name.name) = cs; |
---|
| | members.foreach(x => analyzeMember(cs,x)) |
---|
| |
---|
| | // Analyze a member |
---|
| | private def analyzeMember(ownerClass: ClassSymbol, tree: Member): Unit = |
---|
| | tree.match { |
---|
| | case FieldDecl(Formal(name, typ)) => |
---|
| | // TODO check that field does not yet exist! |
---|
| | ownerClass.enterField(FieldSymbol(tree.pos, name.name, analyzeType(typ))) |
---|
| | ownerClass.lookupField(name.name) match { |
---|
| | case Some(v) => |
---|
| | Report.error(tree.pos, "Class variable already defined: " + name); |
---|
| | case None => |
---|
| | name.sym= FieldSymbol(tree.pos, name.name, analyzeType(typ)); |
---|
| | ownerClass.enterField(name.sym.asInstanceOf[FieldSymbol]); |
---|
| | } |
---|
| | case MethodDef(name, args, rtype, expr) => |
---|
| | var myVarScope = emptyVarScope; |
---|
| | |
---|
| | for ( val x <- ownerClass.allFields ) myVarScope = myVarScope + x.name -> x.asInstanceOf[VarSymbol]; |
---|
| | |
---|
| | val paramtypes = for ( val f <- args ) yield { |
---|
| | //TODO: check that there isn't already a class field with the same name |
---|
| | f.name.sym = VarSymbol(f.pos, f.name.name, analyzeType(f.typ)); |
---|
| | myVarScope = myVarScope + f.name.name -> f.name.sym.asInstanceOf[VarSymbol]; |
---|
| | analyzeType(f.typ); |
---|
| | } |
---|
| | |
---|
| | val rt = analyzeType(rtype); |
---|
| | checkSubtype(tree.pos, "Return type mismatch", analyzeExpr(myVarScope, expr), rt); |
---|
| | name.sym = MethodSymbol(tree.pos, name.name, paramtypes, rt); |
---|
| | |
---|
| | ownerClass.lookupMethod(name.name) match { |
---|
| | case Some(m) => |
---|
| | var paramtypes = for ( val Formal(x,y) <- args ) yield analyzeType(y); |
---|
| | ownerClass.enterMethod(MethodSymbol(tree.pos, name.name, paramtypes, analyzeType(rtype))) |
---|
| | ownerClass.enterMethod(name.sym.asInstanceOf[MethodSymbol]); |
---|
| | case None => |
---|
| | var paramtypes = for ( val Formal(x,y) <- args ) yield analyzeType(y); |
---|
| | ownerClass.enterNewMethod(MethodSymbol(tree.pos, name.name, paramtypes, analyzeType(rtype))) |
---|
| | ownerClass.enterNewMethod(name.sym.asInstanceOf[MethodSymbol]); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | // Analyze a statement |
---|
| |
---|
| | varScope |
---|
| | case None => |
---|
| | val mt = analyzeType(typ); |
---|
| | checkSubtype(tree.pos, "Incompatible types", analyzeExpr(varScope, expr), mt); |
---|
| | val ms = VarSymbol(tree.pos, name.name, mt); |
---|
| | name.sym = ms; |
---|
| | varScope + name.name -> ms; |
---|
| | name.sym = VarSymbol(tree.pos, name.name, mt); |
---|
| | varScope + name.name -> name.sym.asInstanceOf[VarSymbol]; |
---|
| | } |
---|
| | |
---|
| | case Set(ident, expr) => |
---|
| | varScope.get(ident.name) match { |
---|
| |
---|
| | |