Add type methods
Этот коммит содержится в:
родитель
139ac45cb1
коммит
013b375904
2 изменённых файлов: 37 добавлений и 11 удалений
|
@ -5,6 +5,10 @@ type Thing struct {
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t Thing) String() string {
|
||||||
|
return t.name
|
||||||
|
}
|
||||||
|
|
||||||
const SIX = 6
|
const SIX = 6
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -16,7 +20,7 @@ func main() {
|
||||||
println("sumrange(100) =", sumrange(100))
|
println("sumrange(100) =", sumrange(100))
|
||||||
|
|
||||||
thing := Thing{"foo"}
|
thing := Thing{"foo"}
|
||||||
println("thing:", thing.name)
|
println("thing:", thing.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateAnswer() int {
|
func calculateAnswer() int {
|
||||||
|
|
42
tgo.go
42
tgo.go
|
@ -174,7 +174,15 @@ func (c *Compiler) Parse(pkgName string) error {
|
||||||
global.SetLinkage(llvm.PrivateLinkage)
|
global.SetLinkage(llvm.PrivateLinkage)
|
||||||
}
|
}
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
// TODO
|
ms := program.MethodSets.MethodSet(member.Type())
|
||||||
|
for i := 0; i < ms.Len(); i++ {
|
||||||
|
fn := program.MethodValue(ms.At(i))
|
||||||
|
frame, err := c.parseFuncDecl(pkgPrefix, fn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
frames[fn] = frame
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return errors.New("todo: member: " + fmt.Sprintf("%#v", member))
|
return errors.New("todo: member: " + fmt.Sprintf("%#v", member))
|
||||||
}
|
}
|
||||||
|
@ -185,7 +193,8 @@ func (c *Compiler) Parse(pkgName string) error {
|
||||||
member := pkg.Members[name]
|
member := pkg.Members[name]
|
||||||
fmt.Println("member:", member.Token(), member)
|
fmt.Println("member:", member.Token(), member)
|
||||||
|
|
||||||
if member, ok := member.(*ssa.Function); ok {
|
switch member := member.(type) {
|
||||||
|
case *ssa.Function:
|
||||||
if member.Blocks == nil {
|
if member.Blocks == nil {
|
||||||
continue // external function
|
continue // external function
|
||||||
}
|
}
|
||||||
|
@ -193,6 +202,15 @@ func (c *Compiler) Parse(pkgName string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case *ssa.Type:
|
||||||
|
ms := program.MethodSets.MethodSet(member.Type())
|
||||||
|
for i := 0; i < ms.Len(); i++ {
|
||||||
|
fn := program.MethodValue(ms.At(i))
|
||||||
|
err := c.parseFunc(frames[fn], fn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,15 +259,19 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Compiler) getPackageRelativeName(frame *Frame, name string) string {
|
func (c *Compiler) getFunctionName(pkgPrefix string, fn *ssa.Function) string {
|
||||||
if strings.IndexByte(name, '.') == -1 {
|
if fn.Signature.Recv() != nil {
|
||||||
name = frame.pkgPrefix + "." + name
|
// Method on a defined type.
|
||||||
|
typeName := fn.Params[0].Type().(*types.Named).Obj().Name()
|
||||||
|
return pkgPrefix + "." + typeName + "." + fn.Name()
|
||||||
|
} else {
|
||||||
|
// Bare function.
|
||||||
|
return pkgPrefix + "." + fn.Name()
|
||||||
}
|
}
|
||||||
return name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Compiler) parseFuncDecl(pkgPrefix string, f *ssa.Function) (*Frame, error) {
|
func (c *Compiler) parseFuncDecl(pkgPrefix string, f *ssa.Function) (*Frame, error) {
|
||||||
name := pkgPrefix + "." + f.Name()
|
name := c.getFunctionName(pkgPrefix, f)
|
||||||
frame := &Frame{
|
frame := &Frame{
|
||||||
pkgPrefix: pkgPrefix,
|
pkgPrefix: pkgPrefix,
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -413,7 +435,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, instr *ssa.CallCommon, call *ssa.B
|
||||||
func (c *Compiler) parseFunctionCall(frame *Frame, call *ssa.CallCommon, fn *ssa.Function) (llvm.Value, error) {
|
func (c *Compiler) parseFunctionCall(frame *Frame, call *ssa.CallCommon, fn *ssa.Function) (llvm.Value, error) {
|
||||||
fmt.Printf(" function: %s\n", fn)
|
fmt.Printf(" function: %s\n", fn)
|
||||||
|
|
||||||
name := c.getPackageRelativeName(frame, fn.Name())
|
name := c.getFunctionName(frame.pkgPrefix, fn)
|
||||||
target := c.mod.NamedFunction(name)
|
target := c.mod.NamedFunction(name)
|
||||||
if target.IsNil() {
|
if target.IsNil() {
|
||||||
return llvm.Value{}, errors.New("undefined function: " + name)
|
return llvm.Value{}, errors.New("undefined function: " + name)
|
||||||
|
@ -484,7 +506,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
}
|
}
|
||||||
return c.builder.CreateGEP(val, indices, ""), nil
|
return c.builder.CreateGEP(val, indices, ""), nil
|
||||||
case *ssa.Global:
|
case *ssa.Global:
|
||||||
return c.mod.NamedGlobal(c.getPackageRelativeName(frame, expr.Name())), nil
|
return c.mod.NamedGlobal(expr.Name()), nil
|
||||||
case *ssa.Parameter:
|
case *ssa.Parameter:
|
||||||
llvmFn := c.mod.NamedFunction(frame.name)
|
llvmFn := c.mod.NamedFunction(frame.name)
|
||||||
return llvmFn.Param(frame.params[expr]), nil
|
return llvmFn.Param(frame.params[expr]), nil
|
||||||
|
@ -559,7 +581,7 @@ func (c *Compiler) parseConst(expr *ssa.Const) (llvm.Value, error) {
|
||||||
case constant.String:
|
case constant.String:
|
||||||
str := constant.StringVal(expr.Value)
|
str := constant.StringVal(expr.Value)
|
||||||
strLen := llvm.ConstInt(c.stringLenType, uint64(len(str)), false)
|
strLen := llvm.ConstInt(c.stringLenType, uint64(len(str)), false)
|
||||||
strPtr := c.builder.CreateGlobalStringPtr(str, ".str")
|
strPtr := c.builder.CreateGlobalStringPtr(str, ".str") // TODO: remove \0 at end
|
||||||
strObj := llvm.ConstStruct([]llvm.Value{strLen, strPtr}, false)
|
strObj := llvm.ConstStruct([]llvm.Value{strLen, strPtr}, false)
|
||||||
return strObj, nil
|
return strObj, nil
|
||||||
case constant.Int:
|
case constant.Int:
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче