Example #1
0
func (v *Context) parseFile(path string, module *ast.Module) {
	// Read
	sourcefile, err := lexer.NewSourcefile(path)
	if err != nil {
		setupErr("%s", err.Error())
	}

	// Lex
	sourcefile.Tokens = lexer.Lex(sourcefile)

	// Parse
	parsedFile, deps := parser.Parse(sourcefile)
	module.Trees = append(module.Trees, parsedFile)

	// Add dependencies to parse array
	for _, dep := range deps {
		depname := ast.NewModuleName(dep)
		v.modulesToRead = append(v.modulesToRead, depname)
		v.depGraph.AddDependency(module.Name, depname)

		if _, _, err := v.findModuleDir(depname.ToPath()); err != nil {
			log.Errorln("main", "%s [%s:%d:%d] Couldn't find module `%s`", util.Red("error:"),
				dep.Where().Filename, dep.Where().StartLine, dep.Where().EndLine,
				depname.String())
			log.Errorln("main", "%s", sourcefile.MarkSpan(dep.Where()))
			os.Exit(1)
		}
	}
}
Example #2
0
func parseFiles(files []string) ([]*parser.Module, map[string]*parser.Module) {
	// read source files
	var sourcefiles []*lexer.Sourcefile
	log.Timed("reading sourcefiles", func() {
		for _, file := range files {
			sourcefile, err := lexer.NewSourcefile(file)
			if err != nil {
				setupErr("%s", err.Error())
			}
			sourcefiles = append(sourcefiles, sourcefile)
		}
	})

	// lexing
	log.Timed("lexing phase", func() {
		for _, file := range sourcefiles {
			file.Tokens = lexer.Lex(file)
		}
	})

	// parsing
	var parsedFiles []*parser.ParseTree
	parsedFileMap := make(map[string]*parser.ParseTree)
	log.Timed("parsing phase", func() {
		for _, file := range sourcefiles {
			parsedFile := parser.Parse(file)
			parsedFiles = append(parsedFiles, parsedFile)
			parsedFileMap[parsedFile.Source.Name] = parsedFile
		}
	})

	// construction
	var constructedModules []*parser.Module
	modules := make(map[string]*parser.Module)
	log.Timed("construction phase", func() {
		for _, file := range parsedFiles {
			constructedModules = append(constructedModules, parser.Construct(file, parsedFileMap, modules))
		}
	})

	return constructedModules, modules
}
Example #3
0
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
}
Example #4
0
File: main.go Project: vnev/ark
func parseFiles(inputs []string) ([]*parser.Module, *parser.ModuleLookup) {
	if len(inputs) != 1 {
		setupErr("Please specify only one file or module to build")
	}

	var modulesToRead []*parser.ModuleName
	var modules []*parser.Module
	moduleLookup := parser.NewModuleLookup("")
	depGraph := parser.NewDependencyGraph()

	input := inputs[0]
	if strings.HasSuffix(input, ".ark") {
		// Handle the special case of a single .ark file
		modname := &parser.ModuleName{Parts: []string{"__main"}}
		module := &parser.Module{
			Name:    modname,
			Dirpath: "",
		}
		moduleLookup.Create(modname).Module = module

		// Read
		sourcefile, err := lexer.NewSourcefile(input)
		if err != nil {
			setupErr("%s", err.Error())
		}

		// Lex
		sourcefile.Tokens = lexer.Lex(sourcefile)

		// Parse
		parsedFile, deps := parser.Parse(sourcefile)
		module.Trees = append(module.Trees, parsedFile)

		// Add dependencies to parse array
		for _, dep := range deps {
			depname := parser.NewModuleName(dep)
			modulesToRead = append(modulesToRead, depname)
			depGraph.AddDependency(modname, depname)
		}

		modules = append(modules, module)
	} else {
		if strings.ContainsAny(input, `\/. `) {
			setupErr("Invalid module name: %s", input)
		}

		modname := &parser.ModuleName{Parts: strings.Split(input, "::")}
		modulesToRead = append(modulesToRead, modname)
	}

	log.Timed("read/lex/parse phase", "", func() {
		for i := 0; i < len(modulesToRead); i++ {
			modname := modulesToRead[i]

			// Skip already loaded modules
			if _, err := moduleLookup.Get(modname); err == nil {
				continue
			}

			fi, dirpath := findModuleDir(*buildSearchpaths, modname.ToPath())
			if fi == nil {
				setupErr("Couldn't find module `%s`", modname)
			}

			if !fi.IsDir() {
				setupErr("Expected path `%s` to be directory, was file.", dirpath)
			}

			module := &parser.Module{
				Name:    modname,
				Dirpath: dirpath,
			}
			moduleLookup.Create(modname).Module = module

			// Check module children
			childFiles, err := ioutil.ReadDir(dirpath)
			if err != nil {
				setupErr("%s", err.Error())
			}

			for _, childFile := range childFiles {
				if strings.HasPrefix(childFile.Name(), ".") || !strings.HasSuffix(childFile.Name(), ".ark") {
					continue
				}

				actualFile := filepath.Join(dirpath, childFile.Name())

				// Read
				sourcefile, err := lexer.NewSourcefile(actualFile)
				if err != nil {
					setupErr("%s", err.Error())
				}

				// Lex
				sourcefile.Tokens = lexer.Lex(sourcefile)

				// Parse
				parsedFile, deps := parser.Parse(sourcefile)
				module.Trees = append(module.Trees, parsedFile)

				// Add dependencies to parse array
				for _, dep := range deps {
					depname := parser.NewModuleName(dep)
					modulesToRead = append(modulesToRead, depname)
					depGraph.AddDependency(modname, depname)
				}
			}

			modules = append(modules, module)
		}
	})

	// Check for cyclic dependencies (in modules)
	log.Timed("cyclic dependency check", "", func() {
		errs := depGraph.DetectCycles()
		if len(errs) > 0 {
			log.Errorln("main", "error: Encountered cyclic dependecies:")
			for _, cycle := range errs {
				log.Errorln("main", "%s", cycle)
			}
			os.Exit(util.EXIT_FAILURE_SETUP)
		}
	})

	// construction
	log.Timed("construction phase", "", func() {
		for _, module := range modules {
			parser.Construct(module, moduleLookup)

		}
	})

	return modules, moduleLookup
}
Example #5
0
func parseFiles(inputs []string) ([]*parser.Module, *parser.ModuleLookup) {
	var modulesToRead []*parser.ModuleName
	for _, input := range inputs {
		if strings.ContainsAny(input, `\/. `) {
			setupErr("Invalid module name: %s", input)
		}

		modname := &parser.ModuleName{Parts: strings.Split(input, "::")}
		modulesToRead = append(modulesToRead, modname)
	}

	var parsedFiles []*parser.ParseTree
	moduleLookup := parser.NewModuleLookup("")
	depGraph := parser.NewDependencyGraph()

	log.Timed("read/lex/parse phase", "", func() {
		for i := 0; i < len(modulesToRead); i++ {
			modname := modulesToRead[i]
			actualFile := filepath.Join(*buildBasedir, modname.ToPath())

			fi, err := os.Stat(actualFile + ".ark")
			shouldBeDir := false
			if os.IsNotExist(err) {
				fi, err = os.Stat(actualFile)
				shouldBeDir = true
			}

			if err != nil {
				setupErr("%s", err.Error())
			}

			if !fi.IsDir() && shouldBeDir {
				setupErr("Expected file `%s` to be directory, was file.", actualFile)
			}

			// Check lookup
			ll := moduleLookup.Create(modname)
			if ll.Tree == nil {
				if shouldBeDir {
					// Setup dummy parse tree
					ll.Tree = &parser.ParseTree{}
					ll.Tree.Name = modname

					// Setup dummy module
					ll.Module = &parser.Module{}
					ll.Module.Path = actualFile
					ll.Module.Name = modname
					ll.Module.GlobalScope = parser.NewGlobalScope()

					// Check module children
					childFiles, err := ioutil.ReadDir(actualFile)
					if err != nil {
						setupErr("%s", err.Error())
					}

					for _, childFile := range childFiles {
						if strings.HasPrefix(childFile.Name(), ".") {
							continue
						}

						if childFile.IsDir() || strings.HasSuffix(childFile.Name(), ".ark") {
							childmodname := parser.JoinModuleName(modname, strings.TrimSuffix(childFile.Name(), ".ark"))
							modulesToRead = append(modulesToRead, childmodname)

							ll.Module.GlobalScope.UsedModules[childmodname.Last()] = moduleLookup.Create(childmodname)
						}
					}
				} else {
					// Read
					sourcefile, err := lexer.NewSourcefile(actualFile + ".ark")
					if err != nil {
						setupErr("%s", err.Error())
					}

					// Lex
					sourcefile.Tokens = lexer.Lex(sourcefile)

					// Parse
					parsedFile, deps := parser.Parse(sourcefile)
					parsedFile.Name = modname

					parsedFiles = append(parsedFiles, parsedFile)
					ll.Tree = parsedFile

					// Add dependencies to parse array
					for _, dep := range deps {
						depname := parser.NewModuleName(dep)
						modulesToRead = append(modulesToRead, depname)
						depGraph.AddDependency(modname, depname)
					}
				}
			}
		}
	})

	// Check for cyclic dependencies (in modules)
	log.Timed("cyclic dependency check", "", func() {
		errs := depGraph.DetectCycles()
		if len(errs) > 0 {
			log.Errorln("main", "error: Encountered cyclic dependecies:")
			for _, cycle := range errs {
				log.Errorln("main", "%s", cycle)
			}
			os.Exit(util.EXIT_FAILURE_SETUP)
		}
	})

	hasMainFunc := false
	// construction
	var constructedModules []*parser.Module
	log.Timed("construction phase", "", func() {
		for _, file := range parsedFiles {
			mod := parser.Construct(file, moduleLookup)
			constructedModules = append(constructedModules, mod)

			// not terribly efficient, but it's best
			// to catch out earlier on if we have
			// a main function or not rather than
			// figuring out at the codegen phase??
			// maybe??
			// TODO FIXME MAKEPRETTY
			for _, node := range mod.Nodes {
				switch node := node.(type) {
				case *parser.FunctionDecl:
					if node.Function.Name == "main" {
						hasMainFunc = true
						break
					}
				default:
				}
			}
		}
	})

	// 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)
	}

	return constructedModules, moduleLookup
}