Add structured coroutines and explicit error handling
This commit is contained in:
parent
de1262b4cf
commit
fe62e81152
31 changed files with 1701 additions and 325 deletions
192
internal/lang/references.go
Normal file
192
internal/lang/references.go
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
package lang
|
||||
|
||||
import "strings"
|
||||
|
||||
func normalizeClassReferences(program *Program) {
|
||||
classes := map[string]bool{}
|
||||
for _, class := range program.Classes {
|
||||
classes[class.Name] = true
|
||||
}
|
||||
normalize := func(value string) string { return normalizeReferenceType(value, classes) }
|
||||
for i := range program.Interfaces {
|
||||
for j := range program.Interfaces[i].Methods {
|
||||
normalizeSignature(&program.Interfaces[i].Methods[j], normalize)
|
||||
}
|
||||
}
|
||||
for i := range program.Enums {
|
||||
for j := range program.Enums[i].Variants {
|
||||
for k := range program.Enums[i].Variants[j].PayloadTypes {
|
||||
program.Enums[i].Variants[j].PayloadTypes[k] = normalize(program.Enums[i].Variants[j].PayloadTypes[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := range program.Classes {
|
||||
for j := range program.Classes[i].Fields {
|
||||
program.Classes[i].Fields[j].Type = normalize(program.Classes[i].Fields[j].Type)
|
||||
}
|
||||
for j := range program.Classes[i].Methods {
|
||||
normalizeFunction(&program.Classes[i].Methods[j], normalize)
|
||||
}
|
||||
}
|
||||
for i := range program.Workers {
|
||||
for j := range program.Workers[i].Fields {
|
||||
program.Workers[i].Fields[j].Type = normalize(program.Workers[i].Fields[j].Type)
|
||||
normalizeExprTypes(program.Workers[i].Fields[j].Value, normalize)
|
||||
}
|
||||
for j := range program.Workers[i].Methods {
|
||||
normalizeFunction(&program.Workers[i].Methods[j], normalize)
|
||||
}
|
||||
}
|
||||
for i := range program.Functions {
|
||||
normalizeFunction(&program.Functions[i], normalize)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeSignature(signature *FunctionSignature, normalize func(string) string) {
|
||||
for i := range signature.Params {
|
||||
signature.Params[i].Type = normalize(signature.Params[i].Type)
|
||||
}
|
||||
signature.ReturnType = normalize(signature.ReturnType)
|
||||
}
|
||||
|
||||
func normalizeFunction(function *FunctionDecl, normalize func(string) string) {
|
||||
for i := range function.Params {
|
||||
function.Params[i].Type = normalize(function.Params[i].Type)
|
||||
}
|
||||
function.ReturnType = normalize(function.ReturnType)
|
||||
normalizeStmtTypes(function.Body, normalize)
|
||||
}
|
||||
|
||||
func normalizeStmtTypes(statements []Stmt, normalize func(string) string) {
|
||||
for index, statement := range statements {
|
||||
switch value := statement.(type) {
|
||||
case VarDecl:
|
||||
value.Type = normalize(value.Type)
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
statements[index] = value
|
||||
case MultiVarDecl:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case AssignStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case AddAssignStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case MultiAssignStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case ReturnStmt:
|
||||
if value.Value != nil {
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
}
|
||||
case ThrowStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case GoStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case DeferStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case ExprStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case IfStmt:
|
||||
normalizeExprTypes(value.Cond, normalize)
|
||||
normalizeStmtTypes(value.Then, normalize)
|
||||
normalizeStmtTypes(value.Else, normalize)
|
||||
case WhileStmt:
|
||||
normalizeExprTypes(value.Cond, normalize)
|
||||
normalizeStmtTypes(value.Body, normalize)
|
||||
case ForEachStmt:
|
||||
normalizeExprTypes(value.Source, normalize)
|
||||
normalizeStmtTypes(value.Body, normalize)
|
||||
case SelectStmt:
|
||||
for _, c := range value.Cases {
|
||||
normalizeExprTypes(c.Source, normalize)
|
||||
normalizeStmtTypes(c.Body, normalize)
|
||||
}
|
||||
case MatchStmt:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
for _, c := range value.Cases {
|
||||
normalizeStmtTypes(c.Body, normalize)
|
||||
}
|
||||
case TryCatchStmt:
|
||||
value.CatchType = normalize(value.CatchType)
|
||||
normalizeStmtTypes(value.TryBody, normalize)
|
||||
normalizeStmtTypes(value.CatchBody, normalize)
|
||||
statements[index] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeExprTypes(expression Expr, normalize func(string) string) {
|
||||
switch value := expression.(type) {
|
||||
case UnaryExpr:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case NonNullExpr:
|
||||
normalizeExprTypes(value.Value, normalize)
|
||||
case BinaryExpr:
|
||||
normalizeExprTypes(value.Left, normalize)
|
||||
normalizeExprTypes(value.Right, normalize)
|
||||
case SelectorExpr:
|
||||
normalizeExprTypes(value.Receiver, normalize)
|
||||
case SafeSelectorExpr:
|
||||
normalizeExprTypes(value.Receiver, normalize)
|
||||
case IndexExpr:
|
||||
normalizeExprTypes(value.Receiver, normalize)
|
||||
normalizeExprTypes(value.Index, normalize)
|
||||
case EnumVariantExpr:
|
||||
for _, item := range value.Values {
|
||||
normalizeExprTypes(item, normalize)
|
||||
}
|
||||
case LambdaExpr:
|
||||
for i := range value.Params {
|
||||
value.Params[i].Type = normalize(value.Params[i].Type)
|
||||
}
|
||||
normalizeStmtTypes(value.Body, normalize)
|
||||
case CallExpr:
|
||||
skipTypeArgs := false
|
||||
if selector, ok := value.Callee.(SelectorExpr); ok {
|
||||
if root, ok := selector.Receiver.(IdentExpr); ok && root.Name == "sql" {
|
||||
skipTypeArgs = true
|
||||
}
|
||||
}
|
||||
if !skipTypeArgs {
|
||||
for i := range value.TypeArgs {
|
||||
value.TypeArgs[i] = normalize(value.TypeArgs[i])
|
||||
}
|
||||
}
|
||||
normalizeExprTypes(value.Callee, normalize)
|
||||
for _, item := range value.Args {
|
||||
normalizeExprTypes(item, normalize)
|
||||
}
|
||||
for _, item := range value.NamedArgs {
|
||||
normalizeExprTypes(item.Value, normalize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeReferenceType(value string, classes map[string]bool) string {
|
||||
if value == "" {
|
||||
return value
|
||||
}
|
||||
nullable := strings.HasSuffix(value, "?")
|
||||
if nullable {
|
||||
value = strings.TrimSuffix(value, "?")
|
||||
}
|
||||
explicitPointer := strings.HasPrefix(value, "*")
|
||||
if explicitPointer {
|
||||
value = strings.TrimPrefix(value, "*")
|
||||
}
|
||||
if params, result, ok := parseFunctionType(value); ok {
|
||||
for i := range params {
|
||||
params[i] = normalizeReferenceType(params[i], classes)
|
||||
}
|
||||
value = "(" + strings.Join(params, ", ") + ") -> " + normalizeReferenceType(result, classes)
|
||||
} else if base, args, ok := parseGenericType(value); ok {
|
||||
for i := range args {
|
||||
args[i] = normalizeReferenceType(args[i], classes)
|
||||
}
|
||||
value = base + "<" + strings.Join(args, ", ") + ">"
|
||||
} else if classes[value] || explicitPointer {
|
||||
value = "*" + value
|
||||
}
|
||||
if nullable {
|
||||
value += "?"
|
||||
}
|
||||
return value
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue