public virtual DataType ProcessGoodFactor(GoodFactorAst goodFactor) { Guard.Against.Null(goodFactor, nameof(goodFactor)); // { - } strong_factor // 检查能否取符号 var strongFactorType = ProcessStrongFactor(goodFactor.StrongFactor); if (goodFactor.IsNegative && !DataTypeHelper.IsLongOrDouble(strongFactorType)) { throw new SemanticException($"{strongFactorType} cannot be negative"); } if (CodeGenerationEnabled) { if (goodFactor.IsNegative) { Debug.Assert(DataTypeHelper.IsLongOrDouble(strongFactorType)); var negativeOperation = "neg." + DataTypeHelper.Suffix(strongFactorType); ExpressionBucket.AddSingle(negativeOperation); } } return(strongFactorType); }
public void ProcessWhileStatement(WhileStatementAst whileStatement) { Guard.Against.Null(whileStatement, nameof(whileStatement)); var conditionType = ProcessExpression(whileStatement.ConditionExpression); if (!(conditionType == DataType.Bool || conditionType == DataType.Double || conditionType == DataType.Long)) { throw new SemanticException( $"While condition should be of bool, double or long type. Provided: {conditionType}"); } var doneLabel = new Instruction("nop"); var startLabel = new Instruction("nop"); if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(startLabel); } // cond-expr if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.AddRange(ExpressionBucket.Pop()); } // jump(if false) to done if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(new object[] { "br.false", doneLabel }); } // # while-block EnterWhileDefination(new Builders.WhileBuilder(CurrentWhile, startLabel, doneLabel)); ProcessBlockStatement(whileStatement.WhileBlock); LeaveWhileDefination(); // jmp .START if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(Instruction.Pack("br", startLabel)); } // .DONE:nop if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(doneLabel); } }
public virtual DataType ProcessIdentExpression(IdentExpressionAst identExpression) { var name = identExpression.IdentifierToken.Value; if (!SymbolScope.FindSymbolDeep(name, out Symbol symbol)) { throw new SemanticException($"Symbol {name} not exist"); } if (!(symbol is VariableSymbol variableSymbol)) { throw new SemanticException($"Symbol {name} is not const/var"); } // All check ok if (CodeGenerationEnabled) { // load-variable-addr if (variableSymbol.IsGlobal) { var id = variableSymbol.GlobalVariableBuilder.Id; ExpressionBucket.Add(new object[] { "globa", id }); } else { if (variableSymbol.LocalLocation.IsArgument) { var id = variableSymbol.LocalLocation.Id; if (CurrentFunction.ReturnType != DataType.Void) { id++;// because arg0 is ret val } var instruction = Instruction.Pack("arga", id); instruction.Comment = variableSymbol.Name + " (ident-expr)"; ExpressionBucket.Add(instruction); } else { // 局部变量 var id = variableSymbol.LocalLocation.Id; ExpressionBucket.Add(new object[] { "loca", id }); } } // de-reference ExpressionBucket.Add(Instruction.Pack("load.64")); } return(variableSymbol.Type); }
public virtual DataType ProcessFactor(FactorAst factor) { var firstType = ProcessGoodFactor(factor.GoodFactor); if (factor.AsTypeList.Count == 0) { return(firstType); } if (!DataTypeHelper.IsLongOrDouble(firstType)) { throw new SemanticException($"First type '{firstType}' is not double or int"); } var type = firstType; foreach (var a in factor.AsTypeList) { DataType t2; switch (a.TypeToken.Value) { case "int": t2 = DataType.Long; break; case "double": t2 = DataType.Double; break; default: throw new SemanticException($"Wrong type cast: {a.TypeToken.Value}"); } if (CodeGenerationEnabled) { if (type != t2) { var src = DataTypeHelper.Suffix(type); var dst = DataTypeHelper.Suffix(t2); ExpressionBucket.AddSingle(src + "to" + dst); } } type = t2; } return(type); }
public virtual DataType ProcessWeakTerm(WeakTermAst weak) { // Remember to assert each op is +|- var firstType = ProcessTerm(weak.Term); if (weak.OpTerms.Count == 0) { return(firstType); } if (!DataTypeHelper.IsLongOrDouble(firstType)) { throw new SemanticException($"first type '{firstType}' should be int or double"); } char suffix = DataTypeHelper.Suffix(firstType); foreach (var(op, term) in weak.OpTerms) { Debug.Assert(op.Value == Lexical.Tokens.Operator.Plus || op.Value == Lexical.Tokens.Operator.Minus); var termType = ProcessTerm(term); if (termType != firstType) { throw new SemanticException( $"Term type '{termType}' should be equal to first type '{firstType}'"); } if (CodeGenerationEnabled) { if (op.Value == Lexical.Tokens.Operator.Plus) { ExpressionBucket.AddSingle("add." + suffix); } else { ExpressionBucket.AddSingle("sub." + suffix); } } } // list check ok return(firstType); }
public virtual DataType ProcessTerm(TermAst term) { var firstType = ProcessFactor(term.Factor); if (term.OpFactors.Count == 0) { return(firstType); } if (!DataTypeHelper.IsLongOrDouble(firstType)) { throw new SemanticException($"First factor type {firstType} is not int or double"); } char suffix = DataTypeHelper.Suffix(firstType); foreach (var(op, factor) in term.OpFactors) { Debug.Assert(op.Value == Lexical.Tokens.Operator.Mult || op.Value == Lexical.Tokens.Operator.Divide); var factorType = ProcessFactor(factor); if (factorType != firstType) { throw new SemanticException($"Factor type '{factorType}' should equal to first type '{firstType}'"); } if (CodeGenerationEnabled) { if (op.Value == Lexical.Tokens.Operator.Mult) { ExpressionBucket.AddSingle("mul." + suffix); } else { ExpressionBucket.AddSingle("div." + suffix); } } } // list check ok return(firstType); }
public virtual DataType ProcessLiteralExpression(LiteralExpressionAst literalExpression) { if (literalExpression.Literal is UInt64LiteralToken intLiteral) { if (CodeGenerationEnabled) { ExpressionBucket.Add(new object[] { "push", (long)intLiteral.Value }); } return(DataType.Long); } if (literalExpression.Literal is DoubleLiteralToken doubleLiteral) { if (CodeGenerationEnabled) { ExpressionBucket.Add(new object[] { "push", doubleLiteral.Value }); } return(DataType.Double); } if (literalExpression.Literal is StringLiteralToken stringLiteral) { // 字符串应该存全局变量,并把地址(划掉)应该把全局变量号放在栈上 if (CodeGenerationEnabled) { var id = GlobalBuilder.RegisterStringConstant(stringLiteral.Value); ExpressionBucket.Add(Instruction.Pack("push", (long)id)); } return(DataType.String); } if (literalExpression.Literal is CharLiteralToken charLiteral) { if (CodeGenerationEnabled) { ExpressionBucket.Add(new object[] { "push", (long)charLiteral.Value }); } return(DataType.Long); } throw new ArgumentException($"Unknown literal token type: {literalExpression.GetType()}"); }
public virtual void ProcessExpressionStatement(ExpressionStatementAst expressionStatement) { // 表达式语句由 表达式 后接分号组成。表达式如果有值,值将会被丢弃。 var expressionReturnType = ProcessExpression(expressionStatement.Expression); // 因为表达式还在临时bucket里面,所以需要pop出来放在函数bucket里面 if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.AddRange(ExpressionBucket.Pop()); } // 代码生成,如果不是返回void,则丢弃栈顶的值 if (CodeGenerationEnabled) { if (expressionReturnType != DataType.Void) { CurrentFunction.Builder.Bucket.AddSingle("pop"); } } }
public void ProcessReturnStatement(ReturnStatementAst returnStatement) { Guard.Against.Null(returnStatement, nameof(returnStatement)); // return_stmt -> 'return' expr? ';' // 无返回值 - 有返回值 if (!IsInFunction) { throw new SemanticException($"Cannot return out side of function defination"); } var sessId = Guid.NewGuid().ToString() ; // load-retval-addr if (CodeGenerationEnabled && CurrentFunction.ReturnType != DataType.Void) { var instruction = Instruction.Pack("arga", 0); instruction.Comment = "load retval addr " + sessId; CurrentFunction.Builder.Bucket.Add(instruction); } DataType actualReturnType; if (returnStatement.ReturnExpression != null) { actualReturnType = ProcessExpression(returnStatement.ReturnExpression); } else { actualReturnType = DataType.Void; } if (actualReturnType != CurrentFunction.ReturnType) { throw new SemanticException( $"Should return {CurrentFunction.ReturnType}, but return {actualReturnType}"); } // returning-expr; if (actualReturnType == DataType.Void) { Debug.Assert(ExpressionBucket.InstructionList.Count == 0); } if (CodeGenerationEnabled) { var exprCode = ExpressionBucket.Pop(); exprCode.ForEach(p => p.Comment += " " + sessId); CurrentFunction.Builder.Bucket.AddRange(exprCode); } // write-retval if (CodeGenerationEnabled && CurrentFunction.ReturnType != DataType.Void) { if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(new Instruction("store.64")); } } // ret if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(new Instruction("ret") { Comment = " " + sessId }); } }
public bool ProcessIfStatement(IfStatementAst ifStatement) { // 能脱离函数的充要条件: // 1. 不能只有if, 要有else。只有if 相当于 可能脱离。“可能”视为0. // 2. if-block可以脱离 && else也可以脱离 Guard.Against.Null(ifStatement, nameof(ifStatement)); // if_stmt -> 'if' expr block_stmt ('else' (block_stmt | if_stmt))? var conditionType = ProcessExpression(ifStatement.ConditionExpression); if (!(conditionType == DataType.Bool || conditionType == DataType.Double || conditionType == DataType.Long)) { throw new SemanticException( $"If.Condition should be of bool,double or long type. Provided: {conditionType}"); } // codegen: cond-expr if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.AddRange(ExpressionBucket.Pop()); } bool canReturn1 = false; bool canReturn2 = false; if (ifStatement.HasElseAndFollowing) { var else0 = new Instruction("nop"); var done0 = new Instruction("nop"); // jmp-if-false .ELSE0 if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(new object[] { "br.false", else0 }); } // if-block canReturn1 = ProcessBlockStatement(ifStatement.BlockStatement); // jmp .DONE0 if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(new object[] { "br", done0 }); } // .ELSE0: nop if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(else0); } // else-block if (ifStatement.FollowingIf != null) { // if-else-if canReturn2 = ProcessIfStatement(ifStatement.FollowingIf); } else { // if-else canReturn2 = ProcessBlockStatement(ifStatement.FollowingBlock); } // .DONE0: nop if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(done0); } return(canReturn1 && canReturn2); } else { var doneInstruction = new Instruction("nop"); if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(new object[] { "br.false", doneInstruction }); } // if-block canReturn1 = ProcessBlockStatement(ifStatement.BlockStatement); // .DONE if (CodeGenerationEnabled) { CurrentFunction.Builder.Bucket.Add(doneInstruction); } } return(false); }
public virtual void ProcessConstDeclarationStatement(ConstDeclarationStatementAst constDeclaration) { var name = constDeclaration.Name.Value; if (SymbolScope.FindSymbolShallow(name, out Symbol existingSymbol)) { throw new SemanticException( $"Cannot const declare because of duplicated name. " + $"Existing symbol type: {existingSymbol.GetType()}"); } if (!new[] { "int", "double" }.Contains(constDeclaration.Type.Value)) { throw new SemanticException($"Type {constDeclaration.Type.Value} should be int or double"); } var declaringType = constDeclaration.Type.Value switch { "int" => DataType.Long, "double" => DataType.Double, _ => throw new Exception("Not Reached") }; var initialExpressionType = ProcessExpression(constDeclaration.ValueExpression); if (declaringType != initialExpressionType) { throw new SemanticException( $"DeclaringType: {declaringType}, InitialExpressionType: {initialExpressionType}"); } // All check ok var symbol = new VariableSymbol(name, !IsInFunction, true, declaringType); SymbolScope.AddSymbol(symbol); if (CodeGenerationEnabled) { if (symbol.IsGlobal) { GlobalBuilder.RegisterGlobalVariable(symbol); symbol.GlobalVariableBuilder.LoadValueInstructions = ExpressionBucket.Pop(); Debug.Assert(symbol.GlobalVariableBuilder.LoadValueInstructions.Count > 0); } else { CurrentFunction.Builder.RegisterLocalVariable(symbol); // load address CurrentFunction.Builder.Bucket.Add(new object[] { "loca", symbol.LocalLocation.Id }); // load init expr CurrentFunction.Builder.Bucket.AddRange(ExpressionBucket.Pop()); // set memory value CurrentFunction.Builder.Bucket.AddSingle("store.64"); } } }
public virtual DataType ProcessAssignExpression(AssignExpressionAst assignExpression) { // IDENT '=' expr // IDENT 是可以赋值的变量,expr是int或者double var name = assignExpression.Identifier.Value; if (!SymbolScope.FindSymbolDeep(assignExpression.Identifier.Value, out Symbol symbol)) { throw new SemanticException($"Symbol name '{name}' not found"); } if (!(symbol is VariableSymbol variableSymbol)) { throw new SemanticException($"Symbol '{name}' is function symbol, cannot assign value"); } if (variableSymbol.IsConstant) { throw new SemanticException($"Symbol '{name}' is constant, cannot assign value"); } var valueType = ProcessExpression(assignExpression.Expression); if (valueType != variableSymbol.Type) { throw new SemanticException( $"Variable '{name}' is type '{variableSymbol.Type}', but expression is '{valueType}'"); } var valueExpressionCode = ExpressionBucket.Pop(); // All check ok if (CodeGenerationEnabled) { // load-variable-addr if (variableSymbol.IsGlobal) { var id = variableSymbol.GlobalVariableBuilder.Id; ExpressionBucket.Add(new object[] { "globa", id }); } else { if (variableSymbol.LocalLocation.IsArgument) { // 函数参数 (+1) var id = variableSymbol.LocalLocation.Id; if (CurrentFunction.ReturnType != DataType.Void) { id++; } var instruction = Instruction.Pack("arga", id); instruction.Comment = variableSymbol.Name + " call-arg"; ExpressionBucket.Add(instruction); } else { // 局部变量 var id = variableSymbol.LocalLocation.Id; ExpressionBucket.Add(new object[] { "loca", id }); } } // value-expr ExpressionBucket.AddRange(valueExpressionCode); // store.64 ExpressionBucket.Add(new Instruction("store.64")); } return(DataType.Void); }
public virtual DataType ProcessCallExpression(CallExpressionAst callExpression) { var name = callExpression.Identifier.Value; if (!SymbolScope.FindSymbolDeep(name, out Symbol symbol)) { throw new SemanticException($"Symbol name '{name}' not found"); } if (!(symbol is FunctionSymbol functionSymbol)) { throw new SemanticException($"Symbol '{name}' is not function, cannot call."); } // ret-space: 如果是stdlibs,不需要预留空间。如果是返回void的,也不用。 if (CodeGenerationEnabled && !IsStdLibCall(functionSymbol.Name) && functionSymbol.ReturnType != DataType.Void) { ExpressionBucket.Add(new object[] { "push", (long)0 }); } var needCount = functionSymbol.ParamTypes.Count; var providedCount = callExpression.HasParams ? callExpression.ParamList.Parameters.Count : 0; if (needCount != providedCount) { throw new SemanticException($"Function '{name}' needs {needCount} param(s)," + $"but provided {providedCount} param(s)"); } // Now, 0:0 or n:n. Check the types when n:n if (needCount != 0) { var providedTypes = new List <DataType>(); foreach (var parameter in callExpression.ParamList.Parameters) { var expressionType = ProcessExpression(parameter); providedTypes.Add(expressionType); } Debug.Assert(functionSymbol.ParamTypes.Count == providedTypes.Count); if (!functionSymbol.IsParamTypeMatch(providedTypes)) { throw new SemanticException($"Call to function '{name}' cannot match param types"); } } // call func id if (CodeGenerationEnabled) { if (!IsStdLibCall(functionSymbol.Name)) { var funcId = functionSymbol.Builder.Id; ExpressionBucket.Add(Instruction.Pack("call", funcId)); } else { // stdlib calls var opcode = StdLibReference[functionSymbol.Name]; Debug.Assert(opcode != null); ExpressionBucket.Add(new Instruction(opcode)); } } return(functionSymbol.ReturnType); }
public virtual DataType ProcessOperatorExpression(OperatorExpressionAst operatorExpression) { // 注意 https://c0.karenia.cc/c0/expr.html 参数类型必须是数值。 // 所以如果有比较符号,那么它们都得是数值 var firstType = ProcessWeakTerm(operatorExpression.WeakTerm); if (operatorExpression.OpTerms.Count == 0) { return(firstType); } if (operatorExpression.OpTerms.Count > 1) { throw new SemanticException($"List count >1"); } if (!DataTypeHelper.IsLongOrDouble(firstType)) { throw new SemanticException($"List is not empty, first type '{firstType}' should be int or double"); } var(op, weak) = operatorExpression.OpTerms[0]; Debug.Assert(op.IsCompare); var weakTermType = ProcessWeakTerm(weak); if (weakTermType != firstType) { throw new SemanticException( $"A weak term '{weakTermType}' in list not matching first type '{firstType}'"); } // Check ok. Now comparing. var typec = DataTypeHelper.Suffix(firstType); if (CodeGenerationEnabled) { // first do cmp, approx. (a-b) ExpressionBucket.AddSingle("cmp." + typec); switch (op.Value) { case Operator.GreaterThan: ExpressionBucket.AddSingle("set.gt"); break; case Operator.LessThan: ExpressionBucket.AddSingle("set.lt"); break; case Operator.GreaterEqual: // >= equivalent to (not <) ExpressionBucket.AddSingle("set.lt"); ExpressionBucket.AddSingle("not"); break; case Operator.LessEqual: // <= equivalent to (not >) ExpressionBucket.AddSingle("set.gt"); ExpressionBucket.AddSingle("not"); break; case Operator.Equal: ExpressionBucket.AddSingle("not"); break; case Operator.NotEqual: // if not equal, a-b is not 0. (not 0 is true) break; default: throw new Exception("Not Reached"); } ; } return(DataType.Bool); }