diff --git a/docs/readme.md b/docs/readme.md index b531cb4..5348cab 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -512,6 +512,7 @@ The source code structure uses a flat layout without nesting: - [memfile](../src/memfile) - Memory backed file descriptors - [optimizer](../src/optimizer) - Code optimization - [pe](../src/pe) - PE format for Windows executables +- [resolver](../src/resolver) - Type token resolver - [scanner](../src/scanner) - Scanner that parses top-level instructions - [set](../src/set) - Generic set implementation - [ssa](../src/ssa) - Static single assignment types diff --git a/src/compiler/Compile.go b/src/compiler/Compile.go index bf089cc..c82f7bc 100644 --- a/src/compiler/Compile.go +++ b/src/compiler/Compile.go @@ -4,6 +4,7 @@ import ( "git.urbach.dev/cli/q/src/config" "git.urbach.dev/cli/q/src/core" "git.urbach.dev/cli/q/src/errors" + "git.urbach.dev/cli/q/src/resolver" "git.urbach.dev/cli/q/src/scanner" ) @@ -35,7 +36,7 @@ func Compile(build *config.Build) (*core.Environment, error) { // Resolve all types so that we have type information ready // for all functions before parallel compilation starts. - err = env.ResolveTypes() + err = resolver.ResolveTypes(env) if err != nil { return nil, err diff --git a/src/core/Environment.go b/src/core/Environment.go index c5bd08d..bc590da 100644 --- a/src/core/Environment.go +++ b/src/core/Environment.go @@ -139,23 +139,6 @@ func (env *Environment) Package(name string, file *fs.File) *Package { return pkg } -// ResolveTypes resolves all the type tokens in structs, globals and function parameters. -func (env *Environment) ResolveTypes() error { - err := env.parseStructs(env.Structs()) - - if err != nil { - return err - } - - err = env.parseGlobals(env.Globals()) - - if err != nil { - return err - } - - return env.parseParameters(env.Functions()) -} - // Structs returns an iterator over all structs. func (env *Environment) Structs() iter.Seq[*types.Struct] { return func(yield func(*types.Struct) bool) { diff --git a/src/resolver/ResolveTypes.go b/src/resolver/ResolveTypes.go new file mode 100644 index 0000000..4b99402 --- /dev/null +++ b/src/resolver/ResolveTypes.go @@ -0,0 +1,20 @@ +package resolver + +import "git.urbach.dev/cli/q/src/core" + +// ResolveTypes resolves all the type tokens in structs, globals and function parameters. +func ResolveTypes(env *core.Environment) error { + err := parseStructs(env, env.Structs()) + + if err != nil { + return err + } + + err = parseGlobals(env, env.Globals()) + + if err != nil { + return err + } + + return parseParameters(env, env.Functions()) +} \ No newline at end of file diff --git a/src/core/parseGlobals.go b/src/resolver/parseGlobals.go similarity index 65% rename from src/core/parseGlobals.go rename to src/resolver/parseGlobals.go index 0716463..5b3b7e8 100644 --- a/src/core/parseGlobals.go +++ b/src/resolver/parseGlobals.go @@ -1,11 +1,13 @@ -package core +package resolver import ( "iter" + + "git.urbach.dev/cli/q/src/core" ) // parseGlobals parses the tokens of global variables. -func (env *Environment) parseGlobals(globals iter.Seq[*Global]) error { +func parseGlobals(env *core.Environment, globals iter.Seq[*core.Global]) error { for global := range globals { typ, err := env.TypeFromTokens(global.Tokens[1:], global.File) diff --git a/src/core/parseParameters.go b/src/resolver/parseParameters.go similarity index 90% rename from src/core/parseParameters.go rename to src/resolver/parseParameters.go index 9144ed4..0cfe17f 100644 --- a/src/core/parseParameters.go +++ b/src/resolver/parseParameters.go @@ -1,15 +1,16 @@ -package core +package resolver import ( "iter" "strings" + "git.urbach.dev/cli/q/src/core" "git.urbach.dev/cli/q/src/token" "git.urbach.dev/cli/q/src/types" ) // parseParameters parses the tokens of the input and output types. -func (env *Environment) parseParameters(functions iter.Seq[*Function]) error { +func parseParameters(env *core.Environment, functions iter.Seq[*core.Function]) error { for f := range functions { f.Type = &types.Function{ Input: make([]types.Type, len(f.Input)), diff --git a/src/core/parseStruct.go b/src/resolver/parseStruct.go similarity index 71% rename from src/core/parseStruct.go rename to src/resolver/parseStruct.go index cd7aaba..5d98970 100644 --- a/src/core/parseStruct.go +++ b/src/resolver/parseStruct.go @@ -1,13 +1,14 @@ -package core +package resolver import ( + "git.urbach.dev/cli/q/src/core" "git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/fs" "git.urbach.dev/cli/q/src/types" ) // parseStruct parses the field tokens of a single struct. -func (env *Environment) parseStruct(structure *types.Struct, processed map[*types.Struct]recursionState) error { +func parseStruct(env *core.Environment, structure *types.Struct, processed map[*types.Struct]recursionState) error { if processed[structure] == finished { return nil } @@ -28,13 +29,13 @@ func (env *Environment) parseStruct(structure *types.Struct, processed map[*type if isStruct { switch processed[dependency] { case notStarted: - err := env.parseStruct(dependency, processed) + err := parseStruct(env, dependency, processed) if err != nil { return err } case started: - return errors.New(&CycleDetected{A: structure.Name(), B: dependency.Name()}, file, field.Tokens[1:]) + return errors.New(&core.CycleDetected{A: structure.Name(), B: dependency.Name()}, file, field.Tokens[1:]) case finished: } } diff --git a/src/core/parseStructs.go b/src/resolver/parseStructs.go similarity index 60% rename from src/core/parseStructs.go rename to src/resolver/parseStructs.go index 4a373aa..136d170 100644 --- a/src/core/parseStructs.go +++ b/src/resolver/parseStructs.go @@ -1,17 +1,18 @@ -package core +package resolver import ( "iter" + "git.urbach.dev/cli/q/src/core" "git.urbach.dev/cli/q/src/types" ) // parseStructs parses the tokens of the struct field types. -func (env *Environment) parseStructs(structs iter.Seq[*types.Struct]) error { +func parseStructs(env *core.Environment, structs iter.Seq[*types.Struct]) error { processed := map[*types.Struct]recursionState{types.String: finished} for structure := range structs { - err := env.parseStruct(structure, processed) + err := parseStruct(env, structure, processed) if err != nil { return err diff --git a/src/core/recursionState.go b/src/resolver/recursionState.go similarity index 94% rename from src/core/recursionState.go rename to src/resolver/recursionState.go index 2b2f1bf..026e929 100644 --- a/src/core/recursionState.go +++ b/src/resolver/recursionState.go @@ -1,4 +1,4 @@ -package core +package resolver // recursionState represents the processing state while parsing struct types. // It is used to detect cycles when a struct references another struct that is