func LoadRuntime() *ast.Module { runtimeModule := &ast.Module{ Name: &ast.ModuleName{ Parts: []string{"__runtime"}, }, Dirpath: "__runtime", Parts: make(map[string]*ast.Submodule), } sourcefile := &lexer.Sourcefile{ Name: "runtime", Path: "runtime.ark", Contents: []rune(RuntimeSource), NewLines: []int{-1, -1}, } lexer.Lex(sourcefile) tree, deps := parser.Parse(sourcefile) if len(deps) > 0 { panic("INTERNAL ERROR: No dependencies allowed in runtime") } runtimeModule.Trees = append(runtimeModule.Trees, tree) ast.Construct(runtimeModule, nil) ast.Resolve(runtimeModule, nil) for _, submod := range runtimeModule.Parts { ast.Infer(submod) } semantic.SemCheck(runtimeModule, *ignoreUnused) ast.LoadRuntimeModule(runtimeModule) return runtimeModule }
func (v *Context) Build(output string, outputType codegen.OutputType, usedCodegen string, optLevel int) { // Start by loading the runtime runtimeModule := LoadRuntime() // Parse the passed files v.parseFiles() // resolve hasMainFunc := false log.Timed("resolve phase", "", func() { for _, module := range v.modules { ast.Resolve(module, v.moduleLookup) // Use module scope to check for main function mainIdent := module.ModScope.GetIdent(ast.UnresolvedName{Name: "main"}) if mainIdent != nil && mainIdent.Type == ast.IDENT_FUNCTION && mainIdent.Public { hasMainFunc = true } } }) // and here we check if we should // bother continuing any further... if !hasMainFunc { log.Error("main", util.Red("error: ")+"main function not found\n") os.Exit(1) } // type inference log.Timed("inference phase", "", func() { for _, module := range v.modules { for _, submod := range module.Parts { ast.Infer(submod) // Dump AST log.Debugln("main", "AST of submodule `%s/%s`:", module.Name, submod.File.Name) for _, node := range submod.Nodes { log.Debugln("main", "%s", node.String()) } log.Debugln("main", "") } } }) // semantic analysis log.Timed("semantic analysis phase", "", func() { for _, module := range v.modules { semantic.SemCheck(module, *ignoreUnused) } }) // codegen if usedCodegen != "none" { var gen codegen.Codegen switch usedCodegen { case "llvm": gen = &LLVMCodegen.Codegen{ OutputName: output, OutputType: outputType, OptLevel: optLevel, } default: log.Error("main", util.Red("error: ")+"Invalid backend choice `"+usedCodegen+"`") os.Exit(1) } log.Timed("codegen phase", "", func() { mods := v.modules if runtimeModule != nil { mods = append(mods, runtimeModule) } gen.Generate(mods) }) } }