Exemple #1
0
func build(files []string, outputFile string, cg string, outputType LLVMCodegen.OutputType, optLevel int) {
	constructedModules, _ := parseFiles(files)

	// resolve
	log.Timed("resolve phase", "", func() {
		for _, module := range constructedModules {
			res := &parser.Resolver{Module: module}
			vis := parser.NewASTVisitor(res)
			vis.VisitModule(module)
		}
	})

	// type inference
	log.Timed("inference phase", "", func() {
		for _, module := range constructedModules {
			inf := &parser.TypeInferer{Module: module}
			inf.Infer()

			// Dump AST
			log.Debugln("main", "AST of module `%s`:", module.Name)
			for _, node := range module.Nodes {
				log.Debugln("main", "%s", node.String())
			}
			log.Debugln("main", "")
		}
	})

	// semantic analysis
	log.Timed("semantic analysis phase", "", func() {
		for _, module := range constructedModules {
			sem := semantic.NewSemanticAnalyzer(module, *buildOwnership, *ignoreUnused)
			vis := parser.NewASTVisitor(sem)
			vis.VisitModule(module)
			sem.Finalize()
		}
	})

	// codegen
	if cg != "none" {
		var gen codegen.Codegen

		switch cg {
		case "llvm":
			gen = &LLVMCodegen.Codegen{
				OutputName: outputFile,
				OutputType: outputType,
				OptLevel:   optLevel,
			}
		default:
			log.Error("main", util.Red("error: ")+"Invalid backend choice `"+cg+"`")
			os.Exit(1)
		}

		log.Timed("codegen phase", "", func() {
			gen.Generate(constructedModules)
		})
	}

}
Exemple #2
0
func (v *StructLiteralNode) construct(c *Constructor) Expr {
	res := &StructLiteral{}
	if v.Name != nil {
		res.Type = &UnresolvedType{Name: toUnresolvedName(v.Name)}
	}
	res.Values = make(map[string]Expr)
	for idx, member := range v.Members {
		res.Values[member.Value] = c.constructExpr(v.Values[idx])
	}

	if v.Name == nil {
		return res
	} else if typ := c.nameMap.TypeOfNameNode(v.Name); typ == NODE_ENUM_MEMBER {
		enum := &EnumLiteral{}
		enum.Member = v.Name.Name.Value
		enum.Type = &UnresolvedType{Name: toParentName(v.Name)}
		enum.StructLiteral = res
		enum.setPos(v.Where().Start())
		return enum
	} else {
		log.Debugln("constructor", "`%s` was a `%s`", v.Name.Name.Value, typ)
		c.errSpan(v.Name.Name.Where, "Name `%s` is not a struct or a enum member", v.Name.Name.Value)
		return nil
	}
}
Exemple #3
0
func runtimeMustLoadType(mod *Module, name string) Type {
	log.Debugln("runtime", "Loading runtime type: %s", name)
	ident := mod.ModScope.GetIdent(UnresolvedName{Name: name})
	if ident.Type != IDENT_TYPE {
		panic("INTERNAL ERROR: Type not defined in runtime: " + name)
	}
	return ident.Value.(Type)
}
Exemple #4
0
func ExtractTypeVariable(pattern Type, value Type) map[string]Type {
	/*
		Pointer($T), Pointer(int) -> {$T: int}
		Arbitrary depth type => Stack containing breadth first traversal
	*/
	res := make(map[string]Type)

	var (
		ps []Type
		vs []Type
	)
	ps = append(ps, pattern)
	vs = append(vs, value)

	for i := 0; i < len(ps); i++ {
		ppart := ps[i]
		vpart := vs[i]
		log.Debugln("resovle", "\nP = `%s`, V = `%s`", ppart.TypeName(), vpart.TypeName())

		ps = AddChildren(ppart, ps)
		vs = AddChildren(vpart, vs)

		if vari, ok := ppart.(ParameterType); ok {
			log.Debugln("resolve", "P was variable (Name: %s)", vari.Name)
			res[vari.Name] = vpart
			continue
		}

		switch ppart.(type) {
		case PrimitiveType, *NamedType:
			if !ppart.Equals(vpart) {
				log.Errorln("resolve", "%s != %s", ppart.TypeName(), vpart.TypeName())
				panic("Part of type did not match pattern")
			}

		default:
			if reflect.TypeOf(ppart) != reflect.TypeOf(vpart) {
				log.Errorln("resolve", "%T != %T", ppart, vpart)
				panic("Part of type did not match pattern")
			}
		}
	}

	return res
}
Exemple #5
0
func (v *ModuleLookup) Dump(i int) {
	if v.Name != "" {
		log.Debug("main", "%s", strings.Repeat(" ", i))
		log.Debugln("main", "%s", v.Name)
	}

	for _, child := range v.Children {
		child.Dump(i + 1)
	}
}
Exemple #6
0
func (v *Codegen) genAccessGEP(n parser.Expr) llvm.Value {
	switch access := n.(type) {
	case *parser.VariableAccessExpr:
		varType := v.getVariable(access.Variable)
		log.Debugln("codegen", "%v => %v", access.Variable, varType)
		if varType.IsNil() {
			panic("varType was nil")
		}
		gep := v.builder().CreateGEP(varType, []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false)}, "")

		if _, ok := access.GetType().(parser.MutableReferenceType); ok {
			return v.builder().CreateLoad(gep, "")
		}

		if _, ok := access.GetType().(parser.ConstantReferenceType); ok {
			return v.builder().CreateLoad(gep, "")
		}

		return gep

	case *parser.StructAccessExpr:
		gep := v.genAccessGEP(access.Struct)

		typ := access.Struct.GetType().ActualType()

		index := typ.(parser.StructType).VariableIndex(access.Variable)
		return v.builder().CreateStructGEP(gep, index, "")

	case *parser.ArrayAccessExpr:
		gep := v.genAccessGEP(access.Array)
		subscriptExpr := v.genExpr(access.Subscript)

		v.genBoundsCheck(v.builder().CreateLoad(v.builder().CreateStructGEP(gep, 0, ""), ""),
			subscriptExpr, access.Subscript.GetType())

		gep = v.builder().CreateStructGEP(gep, 1, "")

		load := v.builder().CreateLoad(gep, "")

		gepIndexes := []llvm.Value{subscriptExpr}
		return v.builder().CreateGEP(load, gepIndexes, "")

	case *parser.TupleAccessExpr:
		gep := v.genAccessGEP(access.Tuple)

		// TODO: Check overflow
		return v.builder().CreateStructGEP(gep, int(access.Index), "")

	case *parser.DerefAccessExpr:
		return v.genExpr(access.Expr)

	default:
		panic("unhandled access type")
	}
}
Exemple #7
0
func (v *Scope) Dump(depth int) {
	indent := strings.Repeat(" ", depth)

	if depth == 0 {
		log.Debug("parser", indent)
		log.Debugln("parser", "This scope:")
	}

	for name, ident := range v.Idents {
		log.Debug("parser", indent)
		log.Debugln("parser", " %s (%s)", name, ident.Type)
	}

	if v.Outer != nil {
		log.Debug("parser", indent)
		log.Debugln("parser", "Parent scope:")
		v.Outer.Dump(depth + 1)
	}

}
Exemple #8
0
func (v *CallExprNode) construct(c *Constructor) Expr {
	// TODO: when we allow function types, allow all access forms (eg. `thing[0]()``)
	if van, ok := v.Function.(*VariableAccessNode); ok {
		typ := c.nameMap.TypeOfNameNode(van.Name)
		if typ == NODE_FUNCTION {
			res := &CallExpr{
				Arguments:      c.constructExprs(v.Arguments),
				functionSource: c.constructExpr(v.Function),
			}
			res.setPos(v.Where().Start())
			return res
		} else if typ == NODE_ENUM_MEMBER {
			res := &EnumLiteral{
				Member:       van.Name.Name.Value,
				Type:         &UnresolvedType{Name: toParentName(van.Name)},
				TupleLiteral: &TupleLiteral{Members: c.constructExprs(v.Arguments)},
			}
			res.setPos(v.Where().Start())
			return res
		} else if typ.IsType() {
			if len(v.Arguments) > 1 {
				c.errSpan(v.Where(), "Cast cannot recieve more that one argument")
			}

			res := &CastExpr{
				Type: c.constructType(&TypeReferenceNode{Reference: van.Name}),
				Expr: c.constructExpr(v.Arguments[0]),
			}
			res.setPos(v.Where().Start())
			return res
		} else {
			log.Debugln("constructor", "`%s` was a `%s`", van.Name.Name.Value, typ)
			c.errSpan(van.Name.Name.Where, "Name `%s` is not a function or a enum member", van.Name.Name.Value)
			return nil
		}
	} else if sae, ok := v.Function.(*StructAccessNode); ok {
		res := &CallExpr{
			Arguments:      c.constructExprs(v.Arguments),
			functionSource: c.constructExpr(v.Function),
		}

		res.ReceiverAccess = sae.construct(c).(*StructAccessExpr).Struct

		res.setPos(v.Where().Start())
		return res
	} else {
		c.err(van.Name.Name.Where, "Can't call function on this")
		return nil
	}
}
Exemple #9
0
func (v *Codegen) typeToLLVMType(typ ast.Type, gcon *ast.GenericContext) llvm.Type {
	switch typ := typ.(type) {
	case ast.PrimitiveType:
		return v.primitiveTypeToLLVMType(typ)
	case ast.FunctionType:
		return v.functionTypeToLLVMType(typ, true, gcon)
	case ast.StructType:
		return v.structTypeToLLVMType(typ, gcon)
	case ast.PointerType:
		return llvm.PointerType(v.typeRefToLLVMTypeWithOuter(typ.Addressee, gcon), 0)
	case ast.ArrayType:
		return v.arrayTypeToLLVMType(typ, gcon)
	case ast.TupleType:
		return v.tupleTypeToLLVMType(typ, gcon)
	case ast.EnumType:
		return v.enumTypeToLLVMType(typ, gcon)
	case ast.ReferenceType:
		return llvm.PointerType(v.typeRefToLLVMTypeWithOuter(typ.Referrer, gcon), 0)
	case *ast.NamedType:
		switch typ.Type.(type) {
		case ast.StructType, ast.EnumType:
			// If something seems wrong with the code and thie problems seems to come from here,
			// make sure the type doesn't need generics arguments as well.
			// This here ignores them.

			name := ast.TypeReferenceMangledName(ast.MANGLE_ARK_UNSTABLE, &ast.TypeReference{BaseType: typ}, gcon)
			v.addNamedType(typ, name, gcon)
			lt := v.namedTypeLookup[name]

			return lt

		default:
			return v.typeToLLVMType(typ.Type, gcon)
		}
	case *ast.SubstitutionType:
		if gcon == nil {
			panic("gcon == nil when getting substitution type")
		}
		if gcon.GetSubstitutionType(typ) == nil {
			panic("missing generic map entry for type " + typ.TypeName() + " " + fmt.Sprintf("(%p)", typ))
		}
		return v.typeRefToLLVMTypeWithOuter(gcon.GetSubstitutionType(typ), gcon)
	default:
		log.Debugln("codegen", "Type was %s (%s)", typ.TypeName(), reflect.TypeOf(typ))
		panic("Unimplemented type category in LLVM codegen")
	}
}
Exemple #10
0
func (v *Codegen) typeToLLVMType(typ parser.Type) llvm.Type {
	switch typ.(type) {
	case parser.PrimitiveType:
		return v.primitiveTypeToLLVMType(typ.(parser.PrimitiveType))
	case *parser.StructType:
		return v.structTypeToLLVMType(typ.(*parser.StructType))
	case parser.PointerType:
		return llvm.PointerType(v.typeToLLVMType(typ.(parser.PointerType).Addressee), 0)
	case parser.ArrayType:
		return v.arrayTypeToLLVMType(typ.(parser.ArrayType))
	case *parser.TupleType:
		return v.tupleTypeToLLVMType(typ.(*parser.TupleType))
	case *parser.EnumType:
		return v.enumTypeToLLVMType(typ.(*parser.EnumType))
	case *parser.NamedType:
		return v.typeToLLVMType(typ.(*parser.NamedType).Type)
	default:
		log.Debugln("codegen", "Type was %s", typ)
		panic("Unimplemented type category in LLVM codegen")
	}
}
Exemple #11
0
Fichier : type.go Projet : vnev/ark
func (v *Codegen) typeToLLVMType(typ parser.Type) llvm.Type {
	switch typ := typ.(type) {
	case parser.PrimitiveType:
		return v.primitiveTypeToLLVMType(typ)
	case parser.FunctionType:
		return v.functionTypeToLLVMType(typ, true)
	case parser.StructType:
		return v.structTypeToLLVMType(typ)
	case parser.PointerType:
		return llvm.PointerType(v.typeToLLVMType(typ.Addressee), 0)
	case parser.ArrayType:
		return v.arrayTypeToLLVMType(typ)
	case parser.TupleType:
		return v.tupleTypeToLLVMType(typ)
	case parser.EnumType:
		return v.enumTypeToLLVMType(typ)
	case *parser.NamedType:
		nt := typ
		switch nt.Type.(type) {
		case parser.StructType, parser.EnumType:
			v.addNamedType(nt)
			lt := v.namedTypeLookup[nt.MangledName(parser.MANGLE_ARK_UNSTABLE)]
			return lt

		default:
			return v.typeToLLVMType(nt.Type)
		}
	case parser.MutableReferenceType:
		return llvm.PointerType(v.typeToLLVMType(typ.Referrer), 0)
	case parser.ConstantReferenceType:
		return llvm.PointerType(v.typeToLLVMType(typ.Referrer), 0)
	default:
		log.Debugln("codegen", "Type was %s (%s)", typ.TypeName(), reflect.TypeOf(typ))
		panic("Unimplemented type category in LLVM codegen")
	}
}
Exemple #12
0
Fichier : main.go Projet : vnev/ark
func build(files []string, outputFile string, cg string, outputType LLVMCodegen.OutputType, optLevel int) {
	constructedModules, moduleLookup := parseFiles(files)

	// resolve

	hasMainFunc := false
	log.Timed("resolve phase", "", func() {
		for _, module := range constructedModules {
			parser.Resolve(module, moduleLookup)

			// Use module scope to check for main function
			mainIdent := module.ModScope.GetIdent(parser.UnresolvedName{Name: "main"})
			if mainIdent != nil && mainIdent.Type == parser.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 constructedModules {
			for _, submod := range module.Parts {
				inf := &parser.TypeInferer{Submodule: submod}
				inf.Infer()

				// 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 constructedModules {
			for _, submod := range module.Parts {
				sem := semantic.NewSemanticAnalyzer(submod, *buildOwnership, *ignoreUnused)
				vis := parser.NewASTVisitor(sem)
				vis.VisitSubmodule(submod)
				sem.Finalize()
			}
		}
	})

	// codegen
	if cg != "none" {
		var gen codegen.Codegen

		switch cg {
		case "llvm":
			gen = &LLVMCodegen.Codegen{
				OutputName: outputFile,
				OutputType: outputType,
				OptLevel:   optLevel,
			}
		default:
			log.Error("main", util.Red("error: ")+"Invalid backend choice `"+cg+"`")
			os.Exit(1)
		}

		log.Timed("codegen phase", "", func() {
			gen.Generate(constructedModules)
		})
	}

}
Exemple #13
0
func (v *parser) dumpRules() {
	log.Debugln("parser", strings.Join(v.ruleStack, " / "))
}
Exemple #14
0
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)
		})
	}
}