private void VisitNode(ClassDeclaration node) { // catch errors prior to entering class declaration ErrorDescriptor err = node.TypeDescriptor as ErrorDescriptor; if (err != null) { PrintError(err); return; } AbstractNode modifiers = node.Child; AbstractNode identifier = modifiers.Sib; AbstractNode classBody = identifier.Sib; ClassTypeDescriptor desc = node.TypeDescriptor as ClassTypeDescriptor; string mods = String.Join(" ", desc.Modifiers).ToLower(); string name = ((Identifier)identifier).ID; ClassName = name; File.WriteLine(".assembly extern mscorlib {}"); File.WriteLine(".assembly addnums {}"); File.WriteLine(".class {0} {1}", mods, name); File.WriteLine("{"); classBody.Accept(this); File.WriteLine("}"); }
public ErrorDescriptor CombineErrors(ErrorDescriptor err) { ErrorDescriptor comboErr = new ErrorDescriptor(); comboErr.Message = this.Message + "\n" + err.Message; return(comboErr); }
private void VisitNode(LocalVariableDeclarationStatement node) { // catch errors prior to entering local var decl stmt ErrorDescriptor err = node.TypeDescriptor as ErrorDescriptor; if (err != null) { PrintError(err); return; } AbstractNode typeSpecifier = node.Child; AbstractNode localVariableDeclarators = typeSpecifier.Sib; string type = GetIlType(typeSpecifier); List <String> names = GetLocalVarDeclNames(localVariableDeclarators); SetLocalVarDeclNames(names); File.WriteLine(".locals init("); int count = 0; int location; foreach (var name in names) { location = _localVariables.GetVarLocation(name); File.Write($" [{location}] {type} {name}"); File.WriteLine((count < names.Count - 1) ? "," : ""); ++count; } File.WriteLine(")"); }
private string GetIlType(TypeDescriptor desc, AbstractNode typeSpec) { // either the return type is a primitive (can get from the signature) PrimitiveTypeIntDescriptor intDesc = desc as PrimitiveTypeIntDescriptor; NumberTypeDescriptor numDesc = desc as NumberTypeDescriptor; if (intDesc != null || numDesc != null) { return("int32"); } PrimitiveTypeStringDescriptor stringDesc = desc as PrimitiveTypeStringDescriptor; LiteralTypeDescriptor litDesc = desc as LiteralTypeDescriptor; if (stringDesc != null || litDesc != null) { return("string"); } PrimitiveTypeBooleanDescriptor boolDesc = desc as PrimitiveTypeBooleanDescriptor; if (boolDesc != null) { return("bool"); } PrimitiveTypeVoidDescriptor voidDesc = desc as PrimitiveTypeVoidDescriptor; if (voidDesc != null) { return("void"); } // or it is a qualified name (can extract from the node) QualifiedName qName = typeSpec as QualifiedName; if (qName != null) { return(qName.GetStringName()); } // or it is an error ErrorDescriptor err = desc as ErrorDescriptor; if (err != null) { return(err.Message); } return(""); }
private void VisitNode(MethodDeclaration node) { // catch errors prior to entering method declaration ErrorDescriptor err = node.TypeDescriptor as ErrorDescriptor; if (err != null) { PrintError(err); return; } _localVariables.OpenScope(); MethodTypeDescriptor desc = node.TypeDescriptor as MethodTypeDescriptor; if (desc != null) { AbstractNode modifiers = node.Child; AbstractNode typeSpecifier = modifiers.Sib; AbstractNode methodDeclarator = typeSpecifier.Sib; AbstractNode methodBody = methodDeclarator.Sib; AbstractNode methodDeclaratorName = methodDeclarator.Child; AbstractNode parameterList = methodDeclaratorName.Sib; // may be null string name = ((Identifier)methodDeclaratorName).ID; if (!desc.Modifiers.Contains(ModifiersEnums.STATIC) /*&& * name.ToLower().Equals("main")*/) { desc.Modifiers.Add(ModifiersEnums.STATIC); } string mods = String.Join(" ", desc.Modifiers).ToLower(); string typeSpec = GetIlType(desc.ReturnType, typeSpecifier); string argList = GetIlTypeParams(desc.Signature.ParameterTypes); string begin = name.ToLower().Equals("main") ? "\n{\n.entrypoint\n.maxstack 42\n" : "\n{\n.maxstack 42"; string end = "ret\n}"; File.WriteLine($".method {mods} {typeSpec} {name}" + $"({argList}) {begin}"); methodBody.Accept(this); File.WriteLine(end); _localVariables.CloseScope(); } }
private string GetIlType(TypeDescriptor desc) { // either the return type is a primitive (can get from the signature) PrimitiveTypeIntDescriptor intDesc = desc as PrimitiveTypeIntDescriptor; NumberTypeDescriptor numDesc = desc as NumberTypeDescriptor; if (intDesc != null || numDesc != null) { return("int32"); } PrimitiveTypeStringDescriptor stringDesc = desc as PrimitiveTypeStringDescriptor; LiteralTypeDescriptor litDesc = desc as LiteralTypeDescriptor; if (stringDesc != null || litDesc != null) { return("string"); } PrimitiveTypeBooleanDescriptor boolDesc = desc as PrimitiveTypeBooleanDescriptor; if (boolDesc != null) { return("bool"); } PrimitiveTypeVoidDescriptor voidDesc = desc as PrimitiveTypeVoidDescriptor; if (voidDesc != null) { return("void"); } // or it is an error ErrorDescriptor err = desc as ErrorDescriptor; if (err != null) { return(err.Message); } return(""); }
private ErrorDescriptor CheckModifiers(List <ModifiersEnums> mods) { string message; ErrorDescriptor error = null; if (mods.Contains(ModifiersEnums.PRIVATE) && mods.Contains(ModifiersEnums.PUBLIC)) { message = "Cannot contain both modifiers PUBLIC and PRVATE."; error = new ErrorDescriptor(message); } if (mods.Count <= 0) { message = "Must contain at least one modifier PUBLIC, " + "PRIVATE, or STATIC"; error = new ErrorDescriptor(message); } return(error); }
private void VisitNode(MethodCall node) { // catch errors prior to entering method call ErrorDescriptor err = node.TypeDescriptor as ErrorDescriptor; if (err != null) { PrintError(err); return; } MethodTypeDescriptor desc = node.TypeDescriptor as MethodTypeDescriptor; string retType = GetIlType(desc.ReturnType, node); AbstractNode methodReference = node.Child; AbstractNode argumentList = methodReference.Sib; // may be null QualifiedName qualifiedName = methodReference as QualifiedName; string methodName = qualifiedName.GetStringName(); // add arguments argumentList?.Accept(this); // special calls for Write or WriteLine methods if (methodName.ToLower().Equals("write") || methodName.ToLower().Equals("writeline")) { CallWrites(methodName.ToLower(), GetIlTypeParams(desc.Signature.ParameterTypes)); } // call for declared methods w/in program else { string param = (argumentList == null) ? "" : GetIlTypeParams(argumentList); File.WriteLine("call {0} {1}::{2}({3})", retType, ClassName, methodName, param); } }
private void VisitNode(MethodCall node) { AbstractNode methodReference = node.Child; AbstractNode argumentList = methodReference.Sib; // may be null TypeDescriptor descriptor; QualifiedName qualifiedName = methodReference as QualifiedName; if (qualifiedName == null) { descriptor = new ErrorDescriptor ("Only Qualified Name supported for Method Call reference"); } else { // get parameters from method call List <TypeDescriptor> argListTypes = GetParameterTypes(argumentList as ArgumentList); // get parameters (signature) from declared method Attributes attr = Table.lookup(qualifiedName.GetStringName()); MethodTypeDescriptor methodDescriptor = attr.TypeDescriptor as MethodTypeDescriptor; if (methodDescriptor != null) { SignatureDescriptor methodSignature = methodDescriptor.Signature; if (methodSignature != null && ParametersMatch(methodSignature, argListTypes)) { // method descriptor for only current signature MethodTypeDescriptor temp = new MethodTypeDescriptor(); temp.ReturnType = methodDescriptor.ReturnType; temp.Signature.ParameterTypes = argListTypes; temp.Signature.Next = null; descriptor = temp; } else if (methodSignature == null) { descriptor = new ErrorDescriptor ("No signature found for method: " + qualifiedName.GetStringName()); } else { descriptor = new ErrorDescriptor ("No method signature found matching: (" + String.Join(", ", argListTypes) + ")"); } } else { descriptor = new ErrorDescriptor("Method not declared: " + qualifiedName.GetStringName()); } node.TypeDescriptor = descriptor; Attributes methodCallAttr = new Attr(descriptor); methodCallAttr.Kind = Kind.MethodType; node.AttributesRef = methodCallAttr; } }
private TypeDescriptor AssignmentExp(AbstractNode qualName, AbstractNode exp) { QualifiedName name = qualName as QualifiedName; Expression expression = exp as Expression; PrimaryExpression primaryExp = exp as PrimaryExpression; TypeDescriptor nameDesc; if (name != null && (expression != null || primaryExp != null)) { Attributes nameAttr = Table.lookup(name.GetStringName()); qualName.AttributesRef = nameAttr; qualName.TypeDescriptor = nameAttr.TypeDescriptor; exp.Accept(this); // Check for errors // if both types are Error Descriptors, combine errors ErrorDescriptor nameErrDesc = nameAttr.TypeDescriptor as ErrorDescriptor; ErrorDescriptor expErrDesc = exp.TypeDescriptor as ErrorDescriptor; if (nameErrDesc != null && expErrDesc != null) { nameDesc = nameErrDesc.CombineErrors(expErrDesc); } // if one or the other is an error, propagate the error up else if (nameErrDesc != null) { nameDesc = nameAttr.TypeDescriptor; } else if (expErrDesc != null) { nameDesc = exp.TypeDescriptor; } // check that the variable being assigned to is assignable else if (nameAttr.IsAssignable) { // if types compatible, assign successfully assigned type if (TypesCompatible(nameAttr.TypeDescriptor, exp.TypeDescriptor)) { nameDesc = GetAssignmentDesc(nameAttr.TypeDescriptor, exp.TypeDescriptor); } // otherwise, assign new error for incompatible types else { nameDesc = new ErrorDescriptor("Incompatible types: " + "cannot assign " + GetSimpleName(exp.TypeDescriptor) + " to " + GetSimpleName(nameAttr.TypeDescriptor) + " variable"); } } // variable is not assignable else { nameDesc = new ErrorDescriptor(nameAttr + " is not assigable. Cannot assign as " + GetSimpleName(exp.TypeDescriptor)); } } // Assignment not made up of correct parts else { string message = ""; if (name == null && expression == null) { message += "EQUALS expression expects 'QualifiedName' " + "on LHS, but has: " + qualName.GetType().Name + " & 'Expression' or 'PrimaryExression' on " + "RHS, but has " + exp.GetType().Name; } else if (name == null) { message += "EQUALS expression expects 'QualifiedName' on" + " LHS, but has: " + qualName.GetType().Name; } else { message += "EQUALS expression expects 'Expression' or " + "'PrimaryExpression' on RHS, but has: " + exp.GetType().Name; } nameDesc = new ErrorDescriptor(message); } return(nameDesc); }
private void PrintError(ErrorDescriptor node) { File.WriteLine("call void [mscorlib]System.Console::" + $"WriteLine({node.Message})"); }