public void AddNewMember(bool isStatic, ClepsType memberType, string memberName) { Debug.Assert(!DoesClassContainMember(memberName)); if (isStatic) { if (memberType.IsFunctionType) { StaticMemberMethods.Add(memberName, memberType); } else { StaticMemberVariables.Add(memberName, memberType); } } else { if (memberType.IsFunctionType) { MemberMethods.Add(memberName, memberType); } else { MemberVariables.Add(memberName, memberType); } } }
public IMethodRegister CreateMethod(string className, bool isStatic, ClepsType functionType, string functionName) { if (!classesLoaded.ContainsKey(className)) { throw new ArgumentException(String.Format("Class {0} not loaded", className)); } if (!functionType.IsFunctionType) { throw new ArgumentException("Expected function type. Got " + functionType.GetClepsTypeString()); } var classNameToUse = isStatic ? className + ".static" : className; var functionNameAndType = new FunctionNameAndType(classNameToUse, functionName, functionType); var methodList = isStatic ? staticMethods[classNameToUse] : memberMethods[classNameToUse]; if (methodList.Contains(functionNameAndType)) { throw new ArgumentException(String.Format("Function {0} {1} {2} for class {3} already exists", isStatic ? "static" : "", functionType, functionName, className)); } methodList.Add(functionNameAndType); var methodRegister = new JavaScriptMethod(functionType as FunctionClepsType); methodBodies.Add(functionNameAndType, methodRegister); return methodRegister; }
public override object VisitMemberDeclarationStatement([NotNull] ClepsParser.MemberDeclarationStatementContext context) { string memberName = context.FieldName.Name.Text; ClepsClassBuilder classBuilder = ClassManager.GetClassBuilder(FullyQualifiedClassName); if (classBuilder == null) { //This is probably because of some earlier error. Return gracefully return(false); } if (classBuilder.DoesClassContainMember(memberName)) { string errorMessage = String.Format("Class {0} has multiple definitions of member {1}", FullyQualifiedClassName, memberName); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //Don't process this member return(false); } bool isStatic = context.STATIC() != null; ClepsType memberType = Visit(context.typename()) as ClepsType; if (memberType.IsFunctionType) { CodeGenerator.CreateMethod(FullyQualifiedClassName, isStatic, memberType, memberName); } classBuilder.AddNewMember(isStatic, memberType, memberName); return(true); }
public override int VisitRawTypeMapStatment([NotNull] ClepsParser.RawTypeMapStatmentContext context) { string className = String.Join(".", CurrentNamespaceAndClass); ClepsType rawLLVMType = ClepsType.GetBasicType(context.typename()); //make sure this maps to an llvm type LLVMTypeRef?llvmType = ClepsLLVMTypeConvertorInst.GetPrimitiveLLVMTypeOrNull(rawLLVMType); if (llvmType == null) { string errorMessage = String.Format("Class {0} has a raw llvm type mapping to {1} which is not a valid llvm type", className, rawLLVMType.GetTypeName()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(-1); } if (ClassManager.ClassContainsRawLLVMTypeMapping(className)) { string errorMessage = String.Format("Class {0} already has a raw llvm type mapping to {1}. Cannot add another raw type mapping to {2}", className, ClassManager.LoadedClassesAndMembers[className].RawLLVMTypeMap.GetTypeName(), rawLLVMType.GetTypeName()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(-1); } if (ClassManager.RawLLVMTypeMappingExists(rawLLVMType)) { string errorMessage = String.Format("Raw llvm type {0} already has a mapping to {1}. Cannot add another raw type mapping to {2}", rawLLVMType.GetTypeName(), ClassManager.RawLLVMTypeMappingClasses[rawLLVMType].FullyQualifiedName, className); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(-1); } ClassManager.AddRawLLVMTypeMapping(className, rawLLVMType); return(0); }
public void NewMemberSeen(string fullClassName, string memberName, ClepsType memberType, bool isStatic) { if (memberName == "Main" && memberType.IsFunctionType && isStatic) { EntryPoints.Add(fullClassName); } }
public override int VisitClassDeclarationStatements([NotNull] ClepsParser.ClassDeclarationStatementsContext context) { if (context.ClassName == null) { //Some antlr parsing exception has occurred. Just exit. return(-1); } CurrentNamespaceAndClass.Add(context.ClassName.GetText()); string className = String.Join(".", CurrentNamespaceAndClass); ClepsClass classDetails; if (!ClassManager.LoadedClassesAndMembers.TryGetValue(className, out classDetails)) { //if the class was not found in the loaded class stage, then this is probably due to an earlier parsing error, just stop processing this class return(-1); } var ret = VisitChildren(context); ClepsType classType = ClepsType.GetBasicType(className, new List <uint>() /* array dims */, 0 /* ptrIndirectionLevel */); LLVMTypeRef?structType = ClepsLLVMTypeConvertorInst.GetLLVMTypeOrNull(classType); Debug.Assert(structType != null); LLVMTypeRef[] memberTypes = GetLLVMTypesArrFromValidClepsTypesList(context, classDetails.MemberVariables.Values.ToList()); LLVM.StructSetBody(structType.Value, memberTypes, false); ValidateClass(context, classDetails); AddConstructor(structType.Value, className); CurrentNamespaceAndClass.RemoveAt(CurrentNamespaceAndClass.Count - 1); return(ret); }
/// <summary> /// Return an LLVM variable defined on the stack. /// The value of the initialized to this variable needs to be a stored in a register. /// This native llvm type is then mapped to the appropriate cleps type (which is specified in code by the rawtypemap statement) and returned /// </summary> /// <param name="context"></param> /// <param name="llvmType"></param> /// <param name="value"></param> /// <returns></returns> private LLVMRegister GetIntRegisterOfClepsType(ParserRuleContext context, LLVMTypeRef llvmType, LLVMValueRef register, string friendlyTypeName) { ClepsType clepsType = ClepsLLVMTypeConvertorInst.GetClepsNativeLLVMType(llvmType); ClepsClass mappedClass; if (!ClassManager.RawLLVMTypeMappingClasses.TryGetValue(clepsType, out mappedClass)) { string errorMessage = String.Format("Could not find a raw mapping for type {0}", clepsType.GetTypeName()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(null); } ClepsType mappedClassType = ClepsType.GetBasicType(mappedClass.FullyQualifiedName, 0); LLVMValueRef?instPtr = CallConstructorAllocaForType(context, mappedClassType, friendlyTypeName + "Inst"); if (instPtr == null) { return(null); } //the mapped type is always the first field LLVMValueRef instField = LLVM.BuildStructGEP(Builder, instPtr.Value, 0, friendlyTypeName + "InstField"); LLVMTypeRef instFieldType = LLVM.TypeOf(instField); LLVM.BuildStore(Builder, register, instField); LLVMRegister ret = new LLVMRegister(mappedClassType, instPtr.Value); return(ret); }
public override IMethodValue VisitFunctionAssignment_Ex([NotNull] ClepsParser.FunctionAssignmentContext context) { var oldCurrMethodRegister = CurrMethodGenerator; VariableManager variableManager = new VariableManager(); VariableManagers.Add(variableManager); ClepsType returnType = VoidClepsType.GetVoidType(); if (context.FunctionReturnType != null) { returnType = Visit(context.FunctionReturnType) as ClepsType; } List <ClepsVariable> functionParameters = context._FunctionParameters.Select(p => Visit(p) as ClepsVariable).ToList(); FunctionClepsType functionType = new FunctionClepsType(functionParameters.Select(p => p.VariableType).ToList(), returnType); var newMethod = CodeGenerator.CreateNewMethod(functionType); CurrMethodGenerator = newMethod; CurrMethodGenerator.SetFormalParameterNames(functionParameters.Select(p => p.VariableName).ToList()); functionParameters.ForEach(variable => { variableManager.AddLocalVariable(variable, CurrMethodGenerator.GetFormalParameterRegister(variable.VariableName)); }); Visit(context.statementBlock()); VariableManagers.RemoveAt(VariableManagers.Count - 1); CurrMethodGenerator = oldCurrMethodRegister; return(newMethod); }
public override object VisitFunctionAssignment_Ex([NotNull] ClepsParser.FunctionAssignmentContext context) { VariableManager variableManager = new VariableManager(); VariableManagers.Add(variableManager); ClepsType returnType = VoidType.GetVoidType(); if (context.FunctionReturnType != null) { returnType = Visit(context.FunctionReturnType) as ClepsType; } List <ClepsType> parameterTypes = context._FunctionParameterTypes.Select(t => Visit(context.FunctionReturnType) as ClepsType).ToList(); FunctionClepsType functionType = new FunctionClepsType(parameterTypes, returnType); IMethodRegister methodRegister = CodeGenerator.GetMethodRegister(FullyQualifiedClassName, CurrMemberIsStatic, CurrMemberType, CurrMemberName); var formalParameterNames = context._FormalParameters.Select(p => Visit(p) as string).ToList(); methodRegister.SetFormalParameterNames(formalParameterNames); formalParameterNames.Zip(parameterTypes, (name, clepsType) => new ClepsVariable(name, clepsType)) .ToList().ForEach(variable => { variableManager.AddLocalVariable(variable, methodRegister.GetFormalParameterRegister(variable.VariableName)); }); Visit(context.statementBlock()); VariableManagers.RemoveAt(VariableManagers.Count - 1); return(functionType); }
public override object VisitMemberDeclarationStatement([NotNull] ClepsParser.MemberDeclarationStatementContext context) { string memberName = context.FieldName.Name.Text; bool isStatic = context.STATIC() != null; ClepsType memberType = Visit(context.typename()) as ClepsType; var oldMemberName = CurrMemberName; var oldMemberIsStatic = CurrMemberIsStatic; var oldMemberType = CurrMemberType; CurrMemberName = memberName; CurrMemberIsStatic = isStatic; CurrMemberType = memberType; if (context.rightHandExpression() != null) { Visit(context.rightHandExpression()); } CurrMemberName = oldMemberName; CurrMemberIsStatic = oldMemberIsStatic; CurrMemberType = oldMemberType; return true; }
public override object VisitFunctionVariableDeclarationStatement([NotNull] ClepsParser.FunctionVariableDeclarationStatementContext context) { IMethodRegister methodRegister = CodeGenerator.GetMethodRegister(FullyQualifiedClassName, CurrMemberIsStatic, CurrMemberType, CurrMemberName); ClepsType variableType = Visit(context.typename()) as ClepsType; string variableName = Visit(context.variable()) as string; VariableManager variableManager = VariableManagers.Last(); if (!variableManager.IsVariableNameAvailable(variableName)) { string errorMessage = String.Format("Variable {0} is already defined", variableName); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //Use a different variable name to avoid stopping the compilation variableName = variableManager.GetAvailableVariableName(variableName); } ClepsVariable variable = new ClepsVariable(variableName, variableType); IValue value = null; if (context.rightHandExpression() != null) { value = Visit(context.rightHandExpression()) as IValue; if (variable.VariableType != value.ExpressionType) { throw new NotImplementedException("Assignment for non identical types not supported yet"); } } IValueRegister variableRegister = methodRegister.CreateNewVariable(variable, value); variableManager.AddLocalVariable(variable, variableRegister); return(variable); }
public override object VisitMemberDeclarationStatement([NotNull] ClepsParser.MemberDeclarationStatementContext context) { string memberName = context.FieldName.Name.Text; bool isStatic = context.STATIC() != null; ClepsType memberType = Visit(context.typename()) as ClepsType; var oldMemberName = CurrMemberName; var oldMemberIsStatic = CurrMemberIsStatic; var oldMemberType = CurrMemberType; CurrMemberName = memberName; CurrMemberIsStatic = isStatic; CurrMemberType = memberType; if (context.rightHandExpression() != null) { Visit(context.rightHandExpression()); } CurrMemberName = oldMemberName; CurrMemberIsStatic = oldMemberIsStatic; CurrMemberType = oldMemberType; return(true); }
public PointerClepsType(ClepsType baseType) { BaseType = baseType; IsArrayType = false; IsFunctionType = false; IsStaticType = false; }
public IMethodRegister CreateMethod(string className, bool isStatic, ClepsType functionType, string functionName) { if (!classesLoaded.ContainsKey(className)) { throw new ArgumentException(String.Format("Class {0} not loaded", className)); } if (!functionType.IsFunctionType) { throw new ArgumentException("Expected function type. Got " + functionType.GetClepsTypeString()); } var classNameToUse = isStatic ? className + ".static" : className; var functionNameAndType = new FunctionNameAndType(classNameToUse, functionName, functionType); var methodList = isStatic ? staticMethods[classNameToUse] : memberMethods[classNameToUse]; if (methodList.Contains(functionNameAndType)) { throw new ArgumentException(String.Format("Function {0} {1} {2} for class {3} already exists", isStatic ? "static" : "", functionType, functionName, className)); } methodList.Add(functionNameAndType); var methodRegister = new JavaScriptMethod(functionType as FunctionClepsType); methodBodies.Add(functionNameAndType, methodRegister); return(methodRegister); }
public IMethodRegister GetMethodRegister(string className, bool isStatic, ClepsType functionType, string functionName) { string classNameToUse = isStatic ? className + ".static" : className; FunctionNameAndType methodRegisterKey = new FunctionNameAndType(classNameToUse, functionName, functionType); return(methodBodies[methodRegisterKey]); }
private IValue doFunctionCall(ParserRuleContext context, string targetFunctionName, List<IValue> parameters, IValue target, ClepsType targetType, bool allowVoidReturn) { IValue dereferencedTarget = target == null? null : GetDereferencedRegisterOrNull(target); BasicClepsType dereferencedType = target == null? targetType as BasicClepsType : dereferencedTarget.ExpressionType as BasicClepsType; if (dereferencedType == null) { string errorMessage = String.Format("Could not dereference expression on type {0}", targetType.GetClepsTypeString()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //just return something to avoid stalling return CodeGenerator.CreateByte(0); } ClepsClass targetClepsClass = ClassManager.GetClass(dereferencedType.GetClepsTypeString()); List<ClepsVariable> functionOverloads; bool isStatic; if (targetClepsClass.StaticMemberMethods.ContainsKey(targetFunctionName)) { isStatic = true; functionOverloads = targetClepsClass.StaticMemberMethods[targetFunctionName]; } else if (target != null && targetClepsClass.MemberMethods.ContainsKey(targetFunctionName)) { isStatic = false; functionOverloads = targetClepsClass.MemberMethods[targetFunctionName]; } else { string errorMessage = String.Format("Class {0} does not contain a {1}static function called {2}.", targetClepsClass.FullyQualifiedName, target == null? "" : "member or ",targetFunctionName); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //Just return something to avoid stalling compilation return CodeGenerator.CreateByte(0); } int matchedPosition; string fnMatchErrorMessage; if (!FunctionOverloadManager.FindMatchingFunctionType(TypeManager, functionOverloads, parameters, out matchedPosition, out fnMatchErrorMessage)) { Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, fnMatchErrorMessage)); //Just return something to avoid stalling compilation return CodeGenerator.CreateByte(0); } FunctionClepsType chosenFunctionType = functionOverloads[matchedPosition].VariableType as FunctionClepsType; if (!allowVoidReturn && chosenFunctionType.ReturnType == VoidClepsType.GetVoidType()) { string errorMessage = String.Format("Function {0} does not return a value", targetFunctionName); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //Just return something to avoid stalling compilation return CodeGenerator.CreateByte(0); } IValue returnValue = CodeGenerator.GetFunctionCallReturnValue(isStatic? null : dereferencedTarget, dereferencedType, targetFunctionName, chosenFunctionType, parameters); return returnValue; }
public ArrayClepsType(ClepsType baseType, long[] dimensions) { BaseType = baseType; Dimensions = dimensions; IsArrayType = true; IsFunctionType = false; IsStaticType = false; }
public override object VisitVariableDeclaration([NotNull] ClepsParser.VariableDeclarationContext context) { bool isConst = context.CONST() != null; ClepsType clepsType = Visit(context.typename()) as ClepsType; string name = Visit(context.variable()) as string; return(new ClepsVariable(name, clepsType, isConst)); }
public FunctionClepsType(List<ClepsType> parameterTypes, ClepsType returnType) { ParameterTypes = parameterTypes; ReturnType = returnType; IsArrayType = false; IsFunctionType = true; IsStaticType = false; }
public override object VisitPointerType([NotNull] ClepsParser.PointerTypeContext context) { ClepsType basicType = Visit(context.BaseType) as ClepsType; Debug.Assert(basicType != null); var ret = new PointerClepsType(basicType); return(ret); }
public override bool NotNullObjectEquals(ClepsType obj) { if (obj.GetType() != typeof(VoidType)) { return false; } return true; }
public override object VisitFunctionType([NotNull] ClepsParser.FunctionTypeContext context) { List <ClepsType> parameters = context._FunctionParameterTypes.Select(p => Visit(p) as ClepsType).ToList(); ClepsType returnType = Visit(context.FunctionReturnType) as ClepsType; var ret = new FunctionClepsType(parameters, returnType); return(ret); }
public override LLVMRegister VisitMemberAssignmentFunctionDeclarationStatement([NotNull] ClepsParser.MemberAssignmentFunctionDeclarationStatementContext context) { bool isStatic = context.STATIC() != null; ClepsParser.FunctionParametersListContext parametersContext = context.assignmentFunctionDeclarationStatement().functionParametersList(); string functionName = context.assignmentFunctionDeclarationStatement().FunctionName.Text; return(VisitFunctionDeclarationBody(context, ClepsType.GetVoidType(), parametersContext, functionName, isStatic)); }
public IValueRegister GetFormalParameterRegister(string name) { int index = Array.IndexOf(FormalParameters.Keys.ToArray(), name); ClepsType paramType = (ExpressionType as FunctionClepsType).ParameterTypes[index]; JavaScriptRegister register = new JavaScriptRegister(FormalParameters[name], paramType); return(register); }
public override bool NotNullObjectEquals(ClepsType obj) { if (obj.GetType() != typeof(PointerClepsType)) { return false; } PointerClepsType objToCompare = obj as PointerClepsType; return BaseType == objToCompare.BaseType; }
public override bool NotNullObjectEquals(ClepsType obj) { if (obj.GetType() != typeof(ArrayClepsType)) { return false; } ArrayClepsType objToCompare = obj as ArrayClepsType; return BaseType == objToCompare.BaseType && Dimensions.SequenceEqual(objToCompare.Dimensions); }
public override bool NotNullObjectEquals(ClepsType obj) { if (obj.GetType() != typeof(FunctionClepsType)) { return false; } FunctionClepsType objToCompare = obj as FunctionClepsType; return ReturnType == objToCompare.ReturnType && ParameterTypes.SequenceEqual(objToCompare.ParameterTypes); }
public override bool NotNullObjectEquals(ClepsType obj) { if (obj.GetType() != typeof(BasicClepsType)) { return false; } BasicClepsType objToCompare = obj as BasicClepsType; return RawTypeName == objToCompare.RawTypeName; }
public IValueRegister GetArrayElementRegister(IValue value, List <IValue> indexes) { JavaScriptValue valueToUse = value as JavaScriptValue; string code = String.Format("{0}{1}", valueToUse.Expression, String.Join("", indexes.Select(i => "[" + (i as JavaScriptValue).Expression + "]"))); ClepsType returnType = (value.ExpressionType as ArrayClepsType).GetTypeForArrayAccess(indexes.Count); JavaScriptRegister ret = new JavaScriptRegister(code, returnType); return(ret); }
public bool CanAddMemberToClass(string memberName, ClepsType memberType, bool isStatic, out string cantAddReason) { if (memberType.IsFunctionType) { return(CanAddFunctionToClass(memberName, memberType, isStatic, out cantAddReason)); } else { return(CanAddVariableToClass(memberName, memberType, isStatic, out cantAddReason)); } }
public bool CanAddMemberToClass(string memberName, ClepsType memberType, bool isStatic, out string cantAddReason) { if (memberType.IsFunctionType) { return CanAddFunctionToClass(memberName, memberType, isStatic, out cantAddReason); } else { return CanAddVariableToClass(memberName, memberType, isStatic, out cantAddReason); } }
private bool CanAddVariableToClass(string memberName, ClepsType memberType, bool isStatic, out string cantAddReason) { //variable rules are simple. No other member can have the same name var ret = !MemberVariables.ContainsKey(memberName) && !MemberMethods.ContainsKey(memberName) && !StaticMemberVariables.ContainsKey(memberName) && !StaticMemberMethods.ContainsKey(memberName); cantAddReason = ret ? null : String.Format("Class {0} has multiple definitions of member {1}", FullyQualifiedName, memberName); return ret; }
public override object VisitArrayAssignment([NotNull] ClepsParser.ArrayAssignmentContext context) { var arrayElements = context._ArrayElements.Select(a => Visit(a) as IValue).ToList(); var elementTypes = arrayElements.Select(a => a.ExpressionType).ToList(); ClepsType arrayElementType = TypeManager.GetSuperType(elementTypes); ClepsType arrayType = new ArrayClepsType(arrayElementType, new long[] { arrayElements.Count }); IValue arr = CodeGenerator.CreateArray(arrayType, arrayElements); return(arr); }
private LLVMRegister VisitFunctionDeclarationBody ( Antlr4.Runtime.ParserRuleContext context, ClepsType clepsReturnType, ClepsParser.FunctionParametersListContext parametersContext, string functionName, bool isStatic ) { string className = String.Join(".", CurrentNamespaceAndClass); if (!ClassManager.DoesClassContainMember(className, functionName, isStatic)) { //if the member was not found in the loaded member stage, then this is probably due to an earlier parsing error, just stop processing this member return(null); } FunctionHierarchy.Add(functionName); string fullyQualifiedName = String.Join(".", CurrentNamespaceAndClass.Union(FunctionHierarchy).ToList()); LLVMValueRef currFunc = LLVM.GetNamedFunction(Module, fullyQualifiedName); LLVMBasicBlockRef basicBlock = LLVM.GetFirstBasicBlock(currFunc); LLVM.PositionBuilderAtEnd(Builder, basicBlock); VariableManager.AddBlock(); List <string> paramNames = parametersContext._FunctionParameterNames.Select(p => p.VariableName.Text).ToList(); List <ClepsType> clepsParameterTypes = parametersContext._FunctionParameterTypes.Select(t => ClepsType.GetBasicType(t)).ToList(); if (!isStatic) { ClepsType thisClassType = ClepsType.GetBasicType(className, 1); paramNames.Insert(0, "this"); clepsParameterTypes.Insert(0, thisClassType); } List <LLVMValueRef> paramValueRegisters = currFunc.GetParams().ToList(); paramNames.Zip(clepsParameterTypes, (ParamName, ParamType) => new { ParamName, ParamType }) .Zip(paramValueRegisters, (ParamNameAndType, ParamRegister) => new { ParamNameAndType.ParamName, ParamNameAndType.ParamType, ParamRegister }) .ToList() .ForEach(p => { LLVMValueRef functionParamPtr = LLVM.BuildAlloca(Builder, LLVM.TypeOf(p.ParamRegister), p.ParamName); LLVM.BuildStore(Builder, p.ParamRegister, functionParamPtr); VariableManager.AddLocalVariable(p.ParamName, p.ParamType, functionParamPtr); }); var ret = VisitChildren(context); VariableManager.RemoveBlock(); FunctionHierarchy.RemoveAt(FunctionHierarchy.Count - 1); return(ret); }
public override int VisitMemberAssignmentFunctionDeclarationStatement([NotNull] ClepsParser.MemberAssignmentFunctionDeclarationStatementContext context) { bool isStatic = context.STATIC() != null; var assignmentFunctionDeclarationStatement = context.assignmentFunctionDeclarationStatement(); string functionName = assignmentFunctionDeclarationStatement.FunctionName.Text; ClepsParser.FunctionParametersListContext parameterContext = assignmentFunctionDeclarationStatement.functionParametersList(); var ret = GenerateMemberFunction(context, isStatic, functionName, ClepsType.GetVoidType(), parameterContext); return(ret); }
private bool CanAddVariableToClass(string memberName, ClepsType memberType, bool isStatic, out string cantAddReason) { //variable rules are simple. No other member can have the same name var ret = !MemberVariables.ContainsKey(memberName) && !MemberMethods.ContainsKey(memberName) && !StaticMemberVariables.ContainsKey(memberName) && !StaticMemberMethods.ContainsKey(memberName); cantAddReason = ret ? null : String.Format("Class {0} has multiple definitions of member {1}", FullyQualifiedName, memberName); return(ret); }
public override LLVMRegister VisitMemberFunctionDeclarationStatement([NotNull] ClepsParser.MemberFunctionDeclarationStatementContext context) { bool isStatic = context.STATIC() != null; ClepsParser.TypenameAndVoidContext returnTypeContext = context.functionDeclarationStatement().FunctionReturnType; ClepsType clepsReturnType = ClepsType.GetBasicOrVoidType(returnTypeContext); ClepsParser.FunctionParametersListContext parametersContext = context.functionDeclarationStatement().functionParametersList(); string functionName = context.functionDeclarationStatement().FunctionName.GetText(); return(VisitFunctionDeclarationBody(context, clepsReturnType, parametersContext, functionName, isStatic)); }
private LLVMRegister GenerateAssignmentToRegister(ParserRuleContext context, LLVMRegister targetPtrRegister, LLVMRegister assignmentValuePtrRegister, string assignmentOperator) { string targetClassName = targetPtrRegister.VariableType.RawTypeName; LLVMValueRef assignmentValue = LLVM.BuildLoad(Builder, assignmentValuePtrRegister.LLVMPtrValueRef, "assignmentValue"); if (ClepsLLVMTypeConvertorInst.IsPrimitiveLLVMType(targetPtrRegister.VariableType)) { //if it is a primitive llvmType, the assignment operators are hardcoded //only the = assignment operator is supported for primitive llvm types if (assignmentOperator != "=") { string errorMessage = String.Format("Primitive class {0} does not have assignment operator {1} defined. = is the only assignment operator allowed", targetClassName, assignmentOperator); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(null); } if (targetPtrRegister.VariableType != assignmentValuePtrRegister.VariableType) { string errorMessage = String.Format("Value of type {0} cannot be assigned to variable of type {1}", assignmentValuePtrRegister.VariableType, targetPtrRegister.VariableType); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(null); } LLVM.BuildStore(Builder, assignmentValue, targetPtrRegister.LLVMPtrValueRef); return(null); } else { ClepsClass variableClass = ClassManager.LoadedClassesAndMembers[targetClassName]; if (!variableClass.MemberMethods.ContainsKey(assignmentOperator)) { string errorMessage = String.Format("The class {0} does not have assignment operator {1} defined", targetClassName, assignmentOperator); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(null); } ClepsType assignmentFunctionToCall = variableClass.MemberMethods[assignmentOperator]; if (assignmentFunctionToCall.FunctionParameters.Count != 2 && assignmentFunctionToCall.FunctionParameters[1] != assignmentValuePtrRegister.VariableType) { string errorMessage = String.Format("The class {0} does not have an assignment operator {1} defined that takes parameter {2}", targetClassName, assignmentOperator, assignmentValuePtrRegister.VariableType); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(null); } string assignmentFunctionNameToCall = String.Format("{0}.{1}", targetClassName, assignmentOperator); LLVMValueRef llvmAssignmentFunction = LLVM.GetNamedFunction(Module, assignmentFunctionNameToCall); LLVMValueRef[] parameters = new LLVMValueRef[] { targetPtrRegister.LLVMPtrValueRef, assignmentValue }; LLVM.BuildCall(Builder, llvmAssignmentFunction, parameters, ""); return(null); } }
public override int VisitMemberOperatorFunctionDeclarationStatement([NotNull] ClepsParser.MemberOperatorFunctionDeclarationStatementContext context) { bool isStatic = context.STATIC() != null; var assignmentFunctionDeclarationStatement = context.operatorFunctionDeclarationStatment(); string functionName = assignmentFunctionDeclarationStatement.FunctionName.GetText(); ClepsParser.TypenameContext functionReturnContext = assignmentFunctionDeclarationStatement.FunctionReturnType; ClepsType clepsReturnType = ClepsType.GetBasicType(functionReturnContext); ClepsParser.FunctionParametersListContext parameterContext = assignmentFunctionDeclarationStatement.functionParametersList(); var ret = GenerateMemberFunction(context, isStatic, functionName, clepsReturnType, parameterContext); return(ret); }
private int GenerateMemberFunction(ParserRuleContext context, bool isStatic, string functionName, ClepsType clepsReturnType, ClepsParser.FunctionParametersListContext parameterContext) { string className = String.Join(".", CurrentNamespaceAndClass); FunctionHierarchy.Add(functionName); string fullFunctionName = String.Join(".", FunctionHierarchy); string fullyQualifiedName = String.Format("{0}.{1}", className, fullFunctionName); if (ClassManager.DoesClassContainMember(className, fullFunctionName)) { string errorMessage = String.Format("Class {0} has multiple definitions of member {1}", className, fullFunctionName); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //Don't process this member return(-1); } List <ClepsType> clepsParameterTypes = parameterContext._FunctionParameterTypes.Select(t => ClepsType.GetBasicType(t)).ToList(); if (!isStatic) { ClepsType currentClassPtrType = ClepsType.GetBasicType(className, new List <uint>() /* array dims */, 1 /* */); clepsParameterTypes.Insert(0, currentClassPtrType); } LLVMTypeRef?llvmReturnType = ClepsLLVMTypeConvertorInst.GetLLVMTypeOrNull(clepsReturnType); if (llvmReturnType == null) { string errorMessage = String.Format("Type {0} was not found", clepsReturnType.GetTypeName()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //If the return type is not found, try to continue by assuming a void return. Compiler will still show an error clepsReturnType = ClepsType.GetVoidType(); llvmReturnType = ClepsLLVMTypeConvertorInst.GetLLVMTypeOrNull(clepsReturnType).Value; } LLVMTypeRef[] llvmParameterTypes = GetLLVMTypesArrFromValidClepsTypesList(context, clepsParameterTypes); LLVMTypeRef funcType = LLVM.FunctionType(llvmReturnType.Value, llvmParameterTypes, false); LLVMValueRef newFunc = LLVM.AddFunction(Module, fullyQualifiedName, funcType); LLVMBasicBlockRef blockRef = LLVM.AppendBasicBlockInContext(Context, newFunc, "entry"); LLVM.PositionBuilderAtEnd(Builder, blockRef); ClepsType clepsFunctionType = ClepsType.GetFunctionType(clepsReturnType, clepsParameterTypes); ClassManager.AddNewMember(className, fullFunctionName, isStatic, clepsFunctionType); FunctionHierarchy.RemoveAt(FunctionHierarchy.Count - 1); return(0); }
private void ValidateClass(ParserRuleContext context, ClepsClass clepsClass) { ClepsType rawLLVMTypeMap = clepsClass.RawLLVMTypeMap; if (rawLLVMTypeMap != null) { ClepsType firstMember = clepsClass.MemberVariables.Values.FirstOrDefault(); if (firstMember != rawLLVMTypeMap) { string errorMessage = String.Format("Class {0} is mapped to the raw llvm type {1}. However the first member of this class is of type {2}", clepsClass.FullyQualifiedName, clepsClass.RawLLVMTypeMap.GetTypeName(), firstMember.GetTypeName()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); } } }
public override LLVMRegister VisitIfStatement([NotNull] ClepsParser.IfStatementContext context) { ClepsParser.RightHandExpressionContext condition = context.rightHandExpression(); LLVMRegister expressionValue = Visit(condition); ClepsType nativeBooleanType = ClepsType.GetBasicType("System.LLVMTypes.I1", 0 /* ptr indirection level */); LLVMValueRef?conditionRegisterPtr = null; //handle native llvm boolean type if (expressionValue.VariableType == nativeBooleanType) { conditionRegisterPtr = expressionValue.LLVMPtrValueRef; } //handle cleps llvm boolean type else if (ClassManager.RawLLVMTypeMappingClasses.ContainsKey(nativeBooleanType)) { ClepsClass mappedBooleanClass = ClassManager.RawLLVMTypeMappingClasses[nativeBooleanType]; ClepsType mappedBooleanType = ClepsType.GetBasicType(mappedBooleanClass.FullyQualifiedName, 0 /* ptr indirection level */); if (expressionValue.VariableType == mappedBooleanType) { //if the mapped type exists, then below can never be null, so call value automatically LLVMTypeRef mappedBooleanTypeInLLVM = ClepsLLVMTypeConvertorInst.GetLLVMTypeOrNull(mappedBooleanType).Value; //get the first field in the mapped type - see rawtypemap for more details conditionRegisterPtr = LLVM.BuildStructGEP(Builder, expressionValue.LLVMPtrValueRef, 0, "ifCondBooleanFieldPtr"); } } if (conditionRegisterPtr == null) { string errorMessage = String.Format("The condition expression in the if condition returns type {0} instead of a boolean expression. ", expressionValue.VariableType.GetTypeName()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); //just assume this is condition is true to avoid stalling the compilation conditionRegisterPtr = LLVM.ConstInt(LLVM.Int1TypeInContext(Context), (ulong)1, false); } LLVMValueRef conditionRegister = LLVM.BuildLoad(Builder, conditionRegisterPtr.Value, "ifCondBooleanField"); LLVMValueRef currentFunction = LLVM.GetInsertBlock(Builder).GetBasicBlockParent(); LLVMBasicBlockRef ifThenBlock = LLVM.AppendBasicBlockInContext(Context, currentFunction, "ifthen"); LLVMBasicBlockRef ifEndBlock = LLVM.AppendBasicBlockInContext(Context, currentFunction, "ifend"); LLVM.BuildCondBr(Builder, conditionRegister, ifThenBlock, ifEndBlock); LLVM.PositionBuilderAtEnd(Builder, ifThenBlock); Visit(context.statementBlock()); LLVM.BuildBr(Builder, ifEndBlock); LLVM.PositionBuilderAtEnd(Builder, ifEndBlock); return(expressionValue); }
public IMethodRegister CreateMethod(string className, bool isStatic, ClepsType functionType, string functionName) { string fullFunctionName = className + "." + functionName; FunctionClepsType functionClepsType = functionType as FunctionClepsType; LLVMTypeRef returnLLVMType = GetLLVMType(functionClepsType.ReturnType); LLVMTypeRef[] parameterLLVMTypes = functionClepsType.ParameterTypes.Select(c => GetLLVMType(c)).ToArray(); LLVMTypeRef functionLLVMType = LLVM.FunctionType(returnLLVMType, parameterLLVMTypes, false /* var args */); LLVMValueRef functionRef = LLVM.AddFunction(Module, fullFunctionName, functionLLVMType); LLVMBasicBlockRef block = LLVM.AppendBasicBlockInContext(Context, functionRef, "entry"); LLVM.PositionBuilderAtEnd(Builder, block); var ret = new LLVMMethod(block); return ret; }
public override LLVMRegister VisitFunctionVariableDeclarationStatement([NotNull] ClepsParser.FunctionVariableDeclarationStatementContext context) { ClepsParser.VariableDeclarationStatementContext variableDeclarationStatement = context.variableDeclarationStatement(); string variableName = variableDeclarationStatement.variable().VariableName.Text; if (VariableManager.IsVariableDefined(variableName)) { string errorMessage = String.Format("Variable {0} is already defined", variableName); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(null); } ClepsType clepsVariableType = ClepsType.GetBasicType(variableDeclarationStatement.typename()); LLVMTypeRef? primitiveTypeOrNull = ClepsLLVMTypeConvertorInst.GetPrimitiveLLVMTypeOrNull(clepsVariableType); LLVMValueRef variable; if (primitiveTypeOrNull != null) { variable = LLVM.BuildAlloca(Builder, primitiveTypeOrNull.Value, variableName + "Ptr"); } else if (clepsVariableType.IsPointerType) { LLVMTypeRef?pointerType = ClepsLLVMTypeConvertorInst.GetLLVMTypeOrNull(clepsVariableType); if (pointerType == null) { string errorMessage = String.Format("Could not find type {0}", clepsVariableType.GetTypeName()); Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage)); return(null); } variable = LLVM.BuildAlloca(Builder, pointerType.Value, variableName + "Ptr"); } else { LLVMValueRef?constructorReturn = CallConstructorAllocaForType(context, clepsVariableType, variableName); if (constructorReturn == null) { return(null); } variable = constructorReturn.Value; } VariableManager.AddLocalVariable(variableName, clepsVariableType, variable); LLVMRegister ret = new LLVMRegister(clepsVariableType, variable); return(ret); }
private bool CanAddFunctionToClass(string memberName, ClepsType memberType, bool isStatic, out string cantAddReason) { //for a new member function, no variables, or static functions can have the same name //for a new static function, no variables, or member functions can have the same name if ( (isStatic && ( MemberVariables.ContainsKey(memberName) || MemberMethods.ContainsKey(memberName) || StaticMemberVariables.ContainsKey(memberName)) ) || (!isStatic && ( MemberVariables.ContainsKey(memberName) || StaticMemberVariables.ContainsKey(memberName) || StaticMemberMethods.ContainsKey(memberName)) ) ) { cantAddReason = String.Format("Class {0} has multiple definitions of member {1}", FullyQualifiedName, memberName); return false; } //the name is used by a function in the same class. Check if we can overload the function FunctionClepsType methodMemberType = memberType as FunctionClepsType; List<ClepsVariable> methods; if (isStatic) { methods = StaticMemberMethods.ContainsKey(memberName) ? StaticMemberMethods[memberName] : new List<ClepsVariable>(); } else { methods = MemberMethods.ContainsKey(memberName) ? MemberMethods[memberName] : new List<ClepsVariable>(); } if (FunctionOverloadManager.MatchingFunctionTypeExists(methods.Select(m => m.VariableType as FunctionClepsType).ToList(), methodMemberType)) { cantAddReason = String.Format("Class {0} already has a function {1}{2}.", FullyQualifiedName, memberName, methodMemberType.GetClepsTypeString()); return false; } else { cantAddReason = null; return true; } }
private LLVMTypeRef GetLLVMType(ClepsType clepsType) { string clepsName = clepsType.GetClepsTypeString(); LLVMTypeRef llvmType; if (clepsName.StartsWith("System.RawTypes.")) { if (clepsName == "System.RawTypes.Byte") { llvmType = LLVM.Int1TypeInContext(Context); } else { throw new NotImplementedException("Rawtype " + clepsName + " not supported"); } } else { llvmType = ClassSkeletons[clepsName]; } return llvmType; }
public bool IsSameOrSubTypeOf(ClepsType baseType, ClepsType typeToTest) { return baseType == typeToTest; }
public PointerClepsType(ClepsType baseType) : base(false, false, false, true, false) { BaseType = baseType; }
public JavaScriptRegister(string valueUsed, ClepsType clepsType) { Expression = valueUsed; ExpressionType = clepsType; }
public FunctionClepsType(List<ClepsType> parameterTypes, ClepsType returnType) : base(false, true, false, false, false) { ParameterTypes = parameterTypes; ReturnType = returnType; }
private IValue doFunctionCall(ClepsParser.FunctionCallContext functionCall, ClepsType targetType, bool isMemberFunctionsAccessible, bool allowVoidReturn) { ClepsClass targetClepsClass; if(targetType is BasicClepsType) { targetClepsClass = ClassManager.GetClass(targetType.GetClepsTypeString()); } else if(targetType is BasicStaticClepsType) { targetClepsClass = ClassManager.GetClass(targetType.GetClepsTypeString()); isMemberFunctionsAccessible = false; } else { throw new NotImplementedException("Function calls on non basic types not supported"); } string targetFunctionName = functionCall.FunctionName.GetText(); List<IValue> parameters = functionCall._FunctionParameters.Select(p => Visit(p) as IValue).ToList(); ClepsType functionType = null; if (targetClepsClass.StaticMemberMethods.ContainsKey(targetFunctionName)) { functionType = targetClepsClass.StaticMemberMethods[targetFunctionName]; } else if (isMemberFunctionsAccessible && targetClepsClass.MemberMethods.ContainsKey(targetFunctionName)) { functionType = targetClepsClass.MemberMethods[targetFunctionName]; } if (functionType == null) { string errorMessage = String.Format("Class {0} does not contain a function called {1}", targetClepsClass.FullyQualifiedName, targetFunctionName); Status.AddError(new CompilerError(FileName, functionCall.Start.Line, functionCall.Start.Column, errorMessage)); //Just return something to avoid stalling compilation return CodeGenerator.CreateByte(0); } List<ClepsType> functionOverloads = new List<ClepsType> { functionType }; int matchedPosition; string fnMatchErrorMessage; if (!FunctionOverloadManager.FindMatchingFunctionType(functionOverloads, parameters, out matchedPosition, out fnMatchErrorMessage)) { Status.AddError(new CompilerError(FileName, functionCall.Start.Line, functionCall.Start.Column, fnMatchErrorMessage)); //Just return something to avoid stalling compilation return CodeGenerator.CreateByte(0); } FunctionClepsType chosenFunctionType = functionOverloads[matchedPosition] as FunctionClepsType; if (!allowVoidReturn && chosenFunctionType.ReturnType == VoidType.GetVoidType()) { string errorMessage = String.Format("Function {0} does not return a value", targetFunctionName); Status.AddError(new CompilerError(FileName, functionCall.Start.Line, functionCall.Start.Column, errorMessage)); //Just return something to avoid stalling compilation return CodeGenerator.CreateByte(0); } IValue returnValue = CodeGenerator.GetFunctionCallReturnValue(FullyQualifiedClassName, targetFunctionName, chosenFunctionType, parameters); return returnValue; }
public IMethodRegister GetMethodRegister(string className, bool isStatic, ClepsType functionType, string functionName) { throw new NotImplementedException(); }
public IValue CreateArray(ClepsType arrayType, List<IValue> arrayElements) { throw new NotImplementedException(); }
private IValue doFunctionCall([NotNull] ClepsParser.FunctionCallContext context, IValue target, ClepsType targetType, bool allowVoidReturn) { string targetFunctionName = context.FunctionName.GetText(); List<IValue> parameters = context._FunctionParameters.Select(p => Visit(p) as IValue).ToList(); return doFunctionCall(context, targetFunctionName, parameters, target, targetType, allowVoidReturn); }
public IValueRegister GetConstantMemberFieldRegisterForWrite(string className, string memberName, ClepsType memberType) { JavaScriptRegister ret; if (memberType.IsFunctionType) { ret = new JavaScriptRegister(String.Format("{0}.{1}.prototype.{2}", JavaScriptCodeParameters.TOPLEVELNAMESPACE, className, JavaScriptCodeParameters.GetMangledFunctionName(memberName, memberType as FunctionClepsType)), memberType); } else { ret = new JavaScriptRegister(String.Format("{0}.{1}.prototype.{2}", JavaScriptCodeParameters.TOPLEVELNAMESPACE, className, memberName), memberType); } return ret; }
public ArrayClepsType(ClepsType baseType, long[] dimensions) : base(true, false, false, false, false) { BaseType = baseType; Dimensions = dimensions; }
public IValue CreateArray(ClepsType arrayType, List<IValue> arrayElements) { string elementCode = String.Join(", ", arrayElements.Select(a => (a as JavaScriptValue).Expression).ToList()); return new JavaScriptValue("[" + elementCode + "]", arrayType); }
public IValueRegister GetMemberFieldRegisterFromSameClass(string className, string memberName, ClepsType memberType) { var ret = new JavaScriptRegister("this." + memberName, memberType); return ret; }