public CbMethod getMethod(String mname, AST args, bool lookup) { // get method from dictionary List<CbMethod> methods; if (mname == null || !(Methods.TryGetValue(mname, out methods))) { if (lookup) ReportError(args.LineNumber, "Invalid method: '{0}'", mname); return null; } int desiredArgs = args.NumChildren; // compare parameters foreach (CbMethod method in methods) { int numArgs = method.ArgType.Count; if (numArgs != desiredArgs) { continue; } else { bool matches = true; // compare argument types for (int i = 0; i < numArgs; i++) { if (method.ArgType[i] != args[i].Type) matches = false; } if (matches) return method; } } // report error if function is called with the lookup flag if (lookup) ReportError(args.LineNumber, "Invalid method or method parameter(s): '{0}'", mname); return null; }
// Makes two shallow passes over the declarations inside a class to obtain // the names and types of all consts, methods and structs declared at the // top level; without this info, typechecking cannot begin. private void prePass( AST node ) { addPredeclared(); AST_kary decls = node as AST_kary; if (decls == null || decls.Tag != NodeType.DeclList) throw new Exception("Bad argument passed to prePass"); // make one pass over the declarations just to enter the names of structs into // the Structs table int arity = decls.NumChildren; for( int i = 0; i < arity; i++ ) { AST ch = decls[i]; if (ch.Tag != NodeType.Struct) continue; // it was not a struct declaration string name = ((AST_leaf)(ch[0])).Sval; if (Structs.ContainsKey(name)) ReportError(ch[0].LineNumber, "Duplicate declaration of struct {0}", name); else Structs.Add(name, new CbStruct(name)); } // now make a second pass over the declarations to // 1. add const declarations to the Consts table // 2. add method declarations to the Methods table // 3. fill in the field details for each struct in the Structs table for( int i = 0; i < arity; i++ ) { AST ch = decls[i]; string name; CbType typ; int argsize; switch(ch.Tag) { case NodeType.Struct: CbStruct str; name = ((AST_leaf)(ch[0])).Sval; // find existing struct Structs.TryGetValue(name, out str); // do error checking AST fldlst = ch[1]; AST fld; AST idlst; argsize = fldlst.NumChildren; int idsize; // iterate through the field list for (int j = 0; j < argsize; j++) { // get field declaration fld = fldlst[j]; // find declaration type typ = lookUpType(fld[0]); // get list of variables declared idlst = fld[1]; idsize = idlst.NumChildren; // add all declared variables to the struct for(int k = 0; k < idsize; k++) str.AddField(((AST_leaf)(idlst[k])).Sval, typ); } break; case NodeType.Const: // Add the name and type of this constant to the Consts table name = ((AST_leaf)(ch[1])).Sval; typ = lookUpType(ch[0]); if (Consts.ContainsKey(name)) ReportError(ch[0].LineNumber, "Duplicate declaration of const {0}", name); else Consts.Add(name, typ); break; case NodeType.Method: name = ((AST_leaf)(ch[1])).Sval; ch[2].Accept(this); // check for duplicate method CbMethod existing = getMethod(name, ch[2], false); if (existing != null) { ReportError(ch[0].LineNumber, "Duplicate declaration of method {0}", name); break; } CbType typm = CbType.Void; // create new CbMethod if(ch[0] != null) typm = lookUpType(ch[0]); CbMethod method = new CbMethod(name, typm); // add argument list (full signature) to CbMethod AST args = ch[2]; for (int j = 0; j < args.NumChildren; j++) { method.ArgType.Add(lookUpType(args[j][0])); } // get list of overloaded methods sharing same name List<CbMethod> methods; if (!Methods.TryGetValue(name, out methods)) // if none exist create new list methods = new List<CbMethod>(); // add method to list methods.Add(method); // replace old list of methods with this name with new list Methods[name] = methods; break; default: throw new Exception("Unexpected node type " + ch.Tag); } } }
// given an Ident or an Array node, look up the type representation private CbType lookUpType(AST node) { CbType result = CbType.Error; if (node.Tag == NodeType.Array) { CbType elemType = lookUpType(node[0]); result = CbType.Array(elemType); } else { // it has to be an Ident node result = lookUpIdenType(node); if (result == CbType.Error) { // check if it's a struct string name = ((AST_leaf)node).Sval; if (Structs.ContainsKey(name)) result = Structs[name]; // it's a struct type else ReportError(node.LineNumber, "Unknown type {0}", name); } } node.Type = result; //annotate the node return result; }
private CbType lookUpIdenType(AST node) { string iden = ((AST_leaf)node).Sval; if (iden == "int") return CbType.Int; else if (iden == "string") return CbType.String; else return CbType.Error; }
private void printTag( AST node ) { f.Write("{0}{1} [line {2}]", indentString(indent), node.Tag, node.LineNumber); if (node.Type != null) f.Write(", type {0}", node.Type); }
public override void AddChild( AST newchild ) { children.Add(newchild); }
public virtual void AddChild( AST ch ) { throw new Exception("AddChild only supported for k-ary nodes"); }