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); }
void ProcessIdentExpression_throws_when_symbol_not_found() { var scope = new SymbolScope(); var name = new IdentifierToken("aCounter", default); var ast = new IdentExpressionAst(name); var generator = ConfigureGenerator(scope, mock => { }); Assert.Throws <SemanticException>(() => generator.ProcessIdentExpression(ast)); }
void ProcessIdentExpression_returns_type_when_constvar_ok() { var scope = new SymbolScope(); var funcSymbol = new VariableSymbol("aCounter", true, false, DataType.Long); scope.AddSymbol(funcSymbol); var name = new IdentifierToken("aCounter", default); var ast = new IdentExpressionAst(name); var generator = ConfigureGenerator(scope, mock => { }); Assert.Equal(DataType.Long, generator.ProcessIdentExpression(ast)); }
void ProcessIdentExpression_throws_when_symbol_not_var_or_const() { var scope = new SymbolScope(); var funcSymbol = new FunctionSymbol("aCounter", DataType.Void, new DataType[0]); scope.AddSymbol(funcSymbol); var name = new IdentifierToken("aCounter", default); var ast = new IdentExpressionAst(name); var generator = ConfigureGenerator(scope, mock => { }); Assert.Throws <SemanticException>(() => generator.ProcessIdentExpression(ast)); }