Пример #1
0
        public override bool VisitClassDeclarationStatements_Ex([NotNull] ClepsParser.ClassDeclarationStatementsContext context)
        {
            if (!ClassManager.IsClassBuilderAvailable(FullyQualifiedClassName))
            {
                //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(false);
            }

            if (ClassManager.IsClassBodySet(FullyQualifiedClassName))
            {
                //class body is already set
                //this branch is hit, if the user has an error in code where multiple classes have the same name
                //gracefully exit
                return(false);
            }

            Visit(context.classBodyStatements());


            ClepsClassBuilder classBuilder = ClassManager.GetClassBuilder(FullyQualifiedClassName);
            ClepsClass        classDetails = classBuilder.BuildClass();

            ClassManager.SetClassDefinition(classDetails);
            CodeGenerator.SetClassBodyAndCreateConstructor(classDetails);

            return(true);
        }
Пример #2
0
        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);
            }
        }
Пример #3
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));
                }
            }
        }
Пример #4
0
        public void SetClassBodyAndCreateConstructor(ClepsClass clepsClass)
        {
            if (!classesLoaded.ContainsKey(clepsClass.FullyQualifiedName))
            {
                throw new ArgumentException(String.Format("Class {0} not loaded", clepsClass.FullyQualifiedName));
            }

            if (classesLoaded[clepsClass.FullyQualifiedName] != null)
            {
                throw new ArgumentException(String.Format("Body for class {0} already set", clepsClass.FullyQualifiedName));
            }

            classesLoaded[clepsClass.FullyQualifiedName] = clepsClass;
        }
Пример #5
0
        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);
        }
Пример #6
0
        private void EnsureNamespaceExists(StringBuilder output, ClepsClass clepsClass)
        {
            string currNamespace = clepsClass.GetNamespace();
            var    pieces        = currNamespace.Split('.').ToList();

            for (int i = 1; i <= pieces.Count; i++)
            {
                var currNesting = String.Join(".", pieces.Take(i));
                if (!namespacesCreated.Contains(currNesting))
                {
                    output.AppendFormat("{0}.{1} = {0}.{1} || {{}};\n", TOPLEVELNAMESPACE, currNesting);
                    namespacesCreated.Add(currNesting);
                }
            }
        }
Пример #7
0
        private void GenerateClass(StringBuilder output, ClepsClass clepsClass)
        {
            FunctionClepsType voidFuncType = new FunctionClepsType(new List <ClepsType>(), VoidClepsType.GetVoidType());

            EnsureNamespaceExists(output, clepsClass);
            output.AppendLine(JavaScriptCodeParameters.TOPLEVELNAMESPACE + "." + clepsClass.FullyQualifiedName + " = function() {");
            {
                clepsClass.MemberVariables.ToList().ForEach(kvp => output.AppendFormat("\tthis.{0} = undefined;\n", kvp.Key));

                output.AppendFormat("\tthis.{0}();\n", JavaScriptCodeParameters.GetMangledFunctionName("classInitializer", voidFuncType));
                output.AppendFormat("\t{0}.{1}.{2}();\n", JavaScriptCodeParameters.TOPLEVELNAMESPACE, clepsClass.FullyQualifiedName, JavaScriptCodeParameters.GetMangledFunctionName("classStaticInitializer", voidFuncType));
            }
            output.AppendLine("};");

            GenerateMethodWithBody(output, clepsClass.FullyQualifiedName, "classInitializer", voidFuncType, false, ClassInitializers[clepsClass.FullyQualifiedName]);
            GenerateMethodWithBody(output, clepsClass.FullyQualifiedName, "classStaticInitializer", voidFuncType, true, ClassStaticInitializers[clepsClass.FullyQualifiedName]);
        }
Пример #8
0
 private void GenerateClass(StringBuilder output, ClepsClass clepsClass)
 {
     EnsureNamespaceExists(output, clepsClass);
     //output.AppendLine(TOPLEVELNAMESPACE + "." + clepsClass.FullyQualifiedName + " = function() {");
     //{
     //    output.AppendLine("\tfunction newInst(curr) {");
     //    {
     //        clepsClass.MemberVariables.ToList().ForEach(kvp => output.AppendFormat("\t\tcurr.{0} = {1};\n", kvp.Key, GetTypeInstance(kvp.Value)));
     //        output.AppendLine("\t}");
     //    }
     //    output.AppendLine("\tnewInst(this);");
     //}
     //output.AppendLine("};");
     //clepsClass.MemberMethods.ToList().ForEach(kvp => output.AppendFormat("{0}.{1}.prototype.{2} = {3};\n", TOPLEVELNAMESPACE, clepsClass.FullyQualifiedName, kvp.Key, methodBodies[new FunctionNameAndType(clepsClass.FullyQualifiedName, kvp.Key, kvp.Value)].GetMethodBody()));
     //clepsClass.StaticMemberVariables.ToList().ForEach(kvp => output.AppendFormat("{0}.{1}.{2} = undefined;\n", TOPLEVELNAMESPACE, clepsClass.FullyQualifiedName, kvp.Key));
     //clepsClass.StaticMemberMethods.ToList().ForEach(kvp => output.AppendFormat("{0}.{1}.{2} = {3};\n", TOPLEVELNAMESPACE, clepsClass.FullyQualifiedName, kvp.Key, methodBodies[new FunctionNameAndType(clepsClass.FullyQualifiedName, kvp.Key, kvp.Value)].GetMethodBody()));
     GenerateJavaScriptClass(output, clepsClass.FullyQualifiedName, clepsClass.MemberVariables, clepsClass.MemberMethods, true /* staticInstCheck */);
     GenerateJavaScriptClass(output, clepsClass.FullyQualifiedName + ".static", clepsClass.StaticMemberVariables, clepsClass.StaticMemberMethods, false /* staticInstCheck */);
 }
        public override object VisitFieldOrClassAssignment([NotNull] ClepsParser.FieldOrClassAssignmentContext context)
        {
            List <string> namespaceClassAndFieldHierarchy = context._ClassHierarchy.Select(h => h.GetText()).ToList();
            bool          classFound = false;
            int           i;

            for (i = namespaceClassAndFieldHierarchy.Count; i >= 1; i--)
            {
                string classNameToTest = String.Join(".", namespaceClassAndFieldHierarchy.Take(i).ToList());
                if (ClassManager.IsClassBodySet(classNameToTest))
                {
                    classFound = true;
                    break;
                }
            }

            if (!classFound)
            {
                string errorMessage = String.Format("Could not find class or field {0}", String.Join(".", namespaceClassAndFieldHierarchy));
                Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage));
                //just return something to avoid stalling
                return(CodeGenerator.CreateByte(0));
            }

            string               fullClassName = String.Join(".", namespaceClassAndFieldHierarchy.Take(i).ToList());
            ClepsClass           currentClass  = ClassManager.GetClass(fullClassName);
            BasicStaticClepsType currentType   = new BasicStaticClepsType(fullClassName);
            var fieldAccesses = namespaceClassAndFieldHierarchy.Skip(i).ToList();

            if (fieldAccesses.Count != 0)
            {
                throw new NotImplementedException("Getting fields on static classes is not supported yet");
            }

            IValue ret = CodeGenerator.GetClassStaticInstance(currentType);

            return(ret);
        }
Пример #10
0
        public void SetClassBodyAndCreateConstructor(ClepsClass clepsClass)
        {
            var memberTypes = clepsClass.MemberVariables.Values.Select(c => GetLLVMType(c)).ToArray();

            LLVM.StructSetBody(ClassSkeletons[clepsClass.FullyQualifiedName], memberTypes, false /* packed */);
        }
Пример #11
0
        public override LLVMRegister VisitBinaryOperatorOnExpression([NotNull] ClepsParser.BinaryOperatorOnExpressionContext context)
        {
            LLVMRegister leftExpression  = Visit(context.LeftExpression);
            LLVMRegister rightExpression = Visit(context.RightExpression);

            if (leftExpression.VariableType != rightExpression.VariableType)
            {
                throw new NotImplementedException("Operators on different types are not yet supported");
            }

            string expressionClassName = leftExpression.VariableType.RawTypeName;
            string operatorName        = context.operatorSymbol().GetText();

            if (ClepsLLVMTypeConvertorInst.IsPrimitiveLLVMType(leftExpression.VariableType))
            {
                LLVMValueRef leftValue  = LLVM.BuildLoad(Builder, leftExpression.LLVMPtrValueRef, "leftValue");
                LLVMValueRef rightValue = LLVM.BuildLoad(Builder, rightExpression.LLVMPtrValueRef, "rightValue");
                LLVMRegister ret        = null;

                //will return null if this is not an arithmetic operation
                ret = GenerateNativeArithmeticOperation(context, leftValue, rightValue, operatorName);

                if (ret == null)
                {
                    //will return null if this is not a comparison operation
                    ret = GenerateNativeComparison(context, leftValue, rightValue, operatorName);
                }

                if (ret == null)
                {
                    string errorMessage = String.Format("The native class {0} does not support operator {1}", expressionClassName, operatorName);
                    Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage));
                    //just assume this is operation returns a constant int to avoid stalling the compilation
                    ret = GetConstantIntRegisterOfClepsType(context, LLVM.Int32TypeInContext(Context), 7, "int32" /* friendly type name */);
                }

                return(ret);
            }
            else
            {
                if (!ClassManager.LoadedClassesAndMembers[expressionClassName].DoesClassContainMember(operatorName, false /* search member types only */))
                {
                    string errorMessage = String.Format("The class {0} does not have a operator {1} defined", expressionClassName, operatorName);
                    Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage));
                    //just assume this is operation returns a constant int to avoid stalling the compilation
                    LLVMRegister ret = GetConstantIntRegisterOfClepsType(context, LLVM.Int32TypeInContext(Context), 7, "int32" /* friendly type name */);
                    return(ret);
                }

                ClepsClass variableClass = ClassManager.LoadedClassesAndMembers[expressionClassName];
                if (!variableClass.MemberMethods.ContainsKey(operatorName))
                {
                    string errorMessage = String.Format("The class {0} does not have operator {1} defined", expressionClassName, operatorName);
                    Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage));
                    //just assume this is operation returns a constant int to avoid stalling the compilation
                    LLVMRegister ret = GetConstantIntRegisterOfClepsType(context, LLVM.Int32TypeInContext(Context), 7, "int32" /* friendly type name */);
                    return(ret);
                }

                ClepsType assignmentFunctionToCall = variableClass.MemberMethods[operatorName];
                if (assignmentFunctionToCall.FunctionParameters.Count != 3 && assignmentFunctionToCall.FunctionParameters[1] != leftExpression.VariableType && assignmentFunctionToCall.FunctionParameters[2] != rightExpression.VariableType)
                {
                    string errorMessage = String.Format("The class {0} does not have an operator {1} defined that takes parameter ({2}, {3})", expressionClassName, operatorName, leftExpression.VariableType, rightExpression.VariableType);
                    Status.AddError(new CompilerError(FileName, context.Start.Line, context.Start.Column, errorMessage));
                    //just assume this is operation returns a constant int to avoid stalling the compilation
                    LLVMRegister ret = GetConstantIntRegisterOfClepsType(context, LLVM.Int32TypeInContext(Context), 7, "int32" /* friendly type name */);
                    return(ret);
                }

                string         assignmentFunctionNameToCall = String.Format("{0}.{1}", expressionClassName, operatorName);
                LLVMValueRef   llvmAssignmentFunction       = LLVM.GetNamedFunction(Module, assignmentFunctionNameToCall);
                LLVMValueRef   operatorArg            = LLVM.BuildLoad(Builder, rightExpression.LLVMPtrValueRef, "operatorArg");
                LLVMValueRef[] parameters             = new LLVMValueRef[] { leftExpression.LLVMPtrValueRef, operatorArg };
                LLVMValueRef   operatorReturnRegister = LLVM.BuildCall(Builder, llvmAssignmentFunction, parameters, "operator" + operatorName + "Call");
                LLVMValueRef   operatorReturnPtr      = LLVM.BuildAlloca(Builder, LLVM.TypeOf(operatorReturnRegister), "operatorReturnPtr");
                LLVM.BuildStore(Builder, operatorReturnRegister, operatorReturnPtr);
                ClepsType    returnType     = assignmentFunctionToCall.FunctionReturnType;
                LLVMRegister operatorReturn = new LLVMRegister(returnType, operatorReturnPtr);
                return(operatorReturn);
            }
        }
        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);
        }
Пример #13
0
 public void SetClassBodyAndCreateConstructor(ClepsClass clepsClass)
 {
     ClassesLoaded[clepsClass.FullyQualifiedName] = clepsClass;
 }
Пример #14
0
 public void SetClassDefinition(ClepsClass clepsClass)
 {
     LoadedClasses.Add(clepsClass.FullyQualifiedName, clepsClass);
 }