Skip to content

Commit

Permalink
Merge pull request #26 from crossoverJie/25-compile-type-check
Browse files Browse the repository at this point in the history
  • Loading branch information
crossoverJie authored Nov 8, 2022
2 parents 37cd7bd + 7328749 commit 0b893f2
Show file tree
Hide file tree
Showing 10 changed files with 405 additions and 52 deletions.
2 changes: 1 addition & 1 deletion any_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int v4 =fun3(1,2);
println(v4);
assertEqual(v4,3);
int fun4(any a, any b){
string fun4(any a, any b){
return a+b;
}
string v5 =fun4("10", "20");
Expand Down
28 changes: 28 additions & 0 deletions compile_log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ int[] a=10;
os.Setenv(RuntimeError, "true")
NewCompiler().Compiler(script)
}
func TestTypeFail(t *testing.T) {
script := `
int a="10";
`
os.Setenv(RuntimeError, "true")
NewCompiler().Compiler(script)
}
func TestTypeFail2(t *testing.T) {
script := `
int[] a=10;
`
os.Setenv(RuntimeError, "true")
NewCompiler().CompilerWithoutNative(script)
}
func TestTypeFail3(t *testing.T) {
script := `
int[] a={1,2,"1"};
`
os.Setenv(RuntimeError, "true")
NewCompiler().Compiler(script)
}
func TestTypeFail4(t *testing.T) {
script := `
int[] a={1,2};
`
os.Setenv(RuntimeError, "true")
NewCompiler().Compiler(script)
}
func TestByteFail2(t *testing.T) {
script := `
byte[] a=10;
Expand Down
66 changes: 62 additions & 4 deletions resolver/ref_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func (s *RefResolver) ExitPrimary(ctx *parser.PrimaryContext) {
} else {
s.at.PutSymbolOfNode(ctx, variable)
symbolType = variable.GetType()
symbolType.SetArray(variable.IsArray())
}
}

Expand Down Expand Up @@ -219,7 +220,15 @@ func (s *RefResolver) ExitFunctionCall(ctx *parser.FunctionCallContext) {
if function != nil {
found = true
s.at.PutSymbolOfNode(ctx, function)
s.at.PutTypeOfNode(ctx, function.GetReturnType())
returnType := function.GetReturnType()
if returnType != nil {
// 兼容函数返回的是闭包变量 func int(int) f2 = f1();
newPrimitiveType := symbol.NewPrimitiveTypeWithType(returnType)
s.at.PutTypeOfNode(ctx, newPrimitiveType)
} else {
s.at.PutTypeOfNode(ctx, returnType)

}
}
}

Expand Down Expand Up @@ -255,7 +264,16 @@ func (s *RefResolver) ExitFunctionCall(ctx *parser.FunctionCallContext) {
if functionVariable != nil {
found = true
s.at.PutSymbolOfNode(ctx, functionVariable)
s.at.PutTypeOfNode(ctx, functionVariable.GetType())
if functionVariable.GetType() != nil {
declareFunctionType, ok := functionVariable.GetType().(*symbol.DeclareFunctionType)
if ok {
s.at.PutTypeOfNode(ctx, declareFunctionType.GetReturnType())
} else {
s.at.PutTypeOfNode(ctx, functionVariable.GetType())
}
} else {
s.at.PutTypeOfNode(ctx, functionVariable.GetType())
}
} else {
var paramStr strings.Builder
for _, t := range paramTypes {
Expand All @@ -272,6 +290,24 @@ func (s *RefResolver) ExitFunctionCall(ctx *parser.FunctionCallContext) {

}

// ExitArrayInitializer 数组初始化校验,int[] a={1,2,"1"};
func (s *RefResolver) ExitArrayInitializer(ctx *parser.ArrayInitializerContext) {
arrayType := make([]symbol.Type, 0)
for _, context := range ctx.AllVariableInitializer() {
variableInitializerContext := context.(*parser.VariableInitializerContext)
exprContext := variableInitializerContext.Expr().(*parser.ExprContext)
exprType := s.at.GetTypeOfNode()[exprContext]
for _, exitType := range arrayType {
if !exitType.IsType(exprType) {
s.at.Log(ctx, fmt.Sprintf("cannot use %s as type %s array", exprType.GetName(), exitType.GetName()))
return
}
}

arrayType = append(arrayType, exprType)
}
}

func (s *RefResolver) ExitExpr(ctx *parser.ExprContext) {
if ctx.GetBop() != nil && ctx.GetBop().GetTokenType() == parser.GScriptParserDOT {
// 获取到 xx.age 中写入的 symbol
Expand Down Expand Up @@ -314,7 +350,9 @@ func (s *RefResolver) ExitExpr(ctx *parser.ExprContext) {
variable := s.at.FindVariable(scope, idName)
s.at.PutSymbolOfNode(ctx, variable)
symbolType := variable.GetType()
s.at.PutTypeOfNode(ctx, symbolType)
variable.SetArray(true)
newPrimitiveType := symbol.NewPrimitiveType(symbolType.GetName(), symbolType.IsArray())
s.at.PutTypeOfNode(ctx, newPrimitiveType)
}

if ctx.Primary() != nil {
Expand Down Expand Up @@ -346,13 +384,28 @@ func (s *RefResolver) ExitExpr(ctx *parser.ExprContext) {
deriveType := symbol.GetUpperType(ctx, type1, type2)
s.at.PutTypeOfNode(ctx, deriveType)
case parser.GScriptParserMOD:
if type1 == symbol.Int && type2 == symbol.Int {
if type1.IsType(symbol.Int) && type2.IsType(symbol.Int) {
s.at.PutTypeOfNode(ctx, symbol.Int)
} else {
s.at.Log(ctx, fmt.Sprintf("invalid operation: %s mod %s", type1.GetName(), type2.GetName()))
}
}
}
// n[0] 写入类型
if ctx.LBRACK() != nil && ctx.RBRACK() != nil && len(ctx.AllExpr()) == 2 {
exprContext := ctx.Expr(0).(*parser.ExprContext)
primaryContext := exprContext.Primary().(*parser.PrimaryContext)
if primaryContext.IDENTIFIER() != nil {
// 查出变量 n 的类型
scope := s.at.FindEncloseScopeOfNode(ctx)
variable := s.at.FindVariable(scope, primaryContext.IDENTIFIER().GetText())
getType := variable.GetType()
primitiveType := symbol.NewPrimitiveType(getType.GetName(), getType.IsArray())
primitiveType.SetArray(true)
s.at.PutTypeOfNode(ctx, primitiveType)

}
}
}

// 查询函数的参数列表
Expand All @@ -372,14 +425,19 @@ func (s *RefResolver) ExitLiteral(ctx *parser.LiteralContext) {
if ctx.DECIMAL_LITERAL() != nil {
// 设置标识符类型
s.at.PutTypeOfNode(ctx, symbol.Int)
symbol.Int.SetArray(false)
} else if ctx.FLOAT_LITERAL() != nil {
s.at.PutTypeOfNode(ctx, symbol.Float)
symbol.Float.SetArray(false)
} else if ctx.String_() != nil {
s.at.PutTypeOfNode(ctx, symbol.String)
symbol.String.SetArray(false)
} else if ctx.BOOL_LITERAL() != nil {
s.at.PutTypeOfNode(ctx, symbol.Bool)
symbol.Bool.SetArray(false)
} else if ctx.Nil() != nil {
s.at.PutTypeOfNode(ctx, symbol.Nil)
symbol.Nil.SetArray(false)

}
}
7 changes: 4 additions & 3 deletions resolver/type_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,11 @@ func (t *TypeResolver) ExitTypeType(ctx *parser.TypeTypeContext) {
t.at.PutTypeOfNode(ctx, symbolType)
}
if symbolType != nil {
// 还原为默认值,因为原始类型是常量,为了达到给变量赋值是否为数组,所以每次都要重新赋值,达到变量的效果
symbolType.SetArray(false)
// 当有声明数组返回时,单独新建,不能用全局变量,会被修改 int[] get(int ...a){}
if len(ctx.AllLBRACK()) > 0 && len(ctx.AllRBRACK()) > 0 {
symbolType.SetArray(true)
newPrimitiveType := symbol.NewPrimitiveType(symbolType.GetName(), symbolType.IsArray())
newPrimitiveType.SetArray(true)
t.at.PutTypeOfNode(ctx, newPrimitiveType)

}
}
Expand Down
Loading

0 comments on commit 0b893f2

Please sign in to comment.