From 7cf83b3c01f87d8bbb1c1233f398548c4b46af4e Mon Sep 17 00:00:00 2001 From: vyPal <66716025+vyPal@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:42:49 +0100 Subject: [PATCH] Add classes to header generation --- example/caffeine.h | 23 ++++++++ example/src/use_externally.cffc | 25 ++++++++ src/build.go | 101 ++++++++++++++++++++++++++++++++ src/lib/compiler/compiler.go | 22 +++---- src/lib/compiler/expressions.go | 4 +- src/lib/compiler/statements.go | 34 ++++++----- src/lib/compiler/utils.go | 2 +- 7 files changed, 181 insertions(+), 30 deletions(-) create mode 100644 example/caffeine.h diff --git a/example/caffeine.h b/example/caffeine.h new file mode 100644 index 0000000..5da342a --- /dev/null +++ b/example/caffeine.h @@ -0,0 +1,23 @@ +/* + * This file was automatically generated by CaffeineC. + * Do not edit this file directly. + */ +#ifndef CAFFEINEC_H +#define CAFFEINEC_H +long printf(char * fmt); +long long testing(); +char * malloc(long long size); +class SomeClass +{ +private: +long long something; +public: +void constructor(); +void inc(); +void dec(); +long long get(); +void set(long long newValue); +void add(long long toAdd); +void sub(long long toSub); +}; +#endif diff --git a/example/src/use_externally.cffc b/example/src/use_externally.cffc index e7cdc26..1c7bc96 100644 --- a/example/src/use_externally.cffc +++ b/example/src/use_externally.cffc @@ -5,4 +5,29 @@ extern vararg func printf(fmt: *i8): i32; export func testing(): i64 { printf("Hello, World!\n"); return 0; +} + +export class SomeClass { + private something: i64; + func constructor() { + this.something = 0; + } + func inc() { + this.something = this.something + 1; + } + func dec() { + this.something = this.something - 1; + } + func get(): i64 { + return this.something; + } + func set(newValue: i64) { + this.something = newValue; + } + func add(toAdd: i64) { + this.something = this.something + toAdd; + } + func sub(toSub: i64) { + this.something = this.something + toSub; + } } \ No newline at end of file diff --git a/src/build.go b/src/build.go index a471704..2982a5e 100644 --- a/src/build.go +++ b/src/build.go @@ -9,6 +9,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "sync" "github.com/fatih/color" @@ -364,6 +365,9 @@ func writeHeader(f *os.File, comp *compiler.Compiler) error { } for _, fn := range comp.Module.Funcs { + if strings.Count(fn.Name(), ".") > 0 { + continue + } _, err = f.WriteString(convertCffTypeToCType(fn.Sig.RetType) + " ") if err != nil { return err @@ -414,6 +418,103 @@ func writeHeader(f *os.File, comp *compiler.Compiler) error { } } + for _, c := range comp.Module.TypeDefs { + _, err = f.WriteString("class " + c.Name() + "\n{\nprivate:\n") + if err != nil { + return err + } + + for _, field := range comp.StructFields[c.Name()] { + if !field.Private { + continue + } + _, err = f.WriteString(convertCffTypeToCType(comp.Context.StringToType(field.Type)) + " " + field.Name + ";\n") + if err != nil { + return err + } + } + + _, err = f.WriteString("public:\n") + if err != nil { + return err + } + + for _, field := range comp.StructFields[c.Name()] { + if field.Private { + continue + } + _, err = f.WriteString(convertCffTypeToCType(comp.Context.StringToType(field.Type)) + " " + field.Name + ";\n") + if err != nil { + return err + } + } + + for _, fn := range comp.Module.Funcs { + var parts []string + if strings.Count(fn.Name(), ".") == 0 { + continue + } else { + parts = strings.Split(fn.Name(), ".") + if parts[0] != c.Name() { + continue + } + } + _, err = f.WriteString(convertCffTypeToCType(fn.Sig.RetType) + " ") + if err != nil { + return err + } + + _, err = f.WriteString(parts[1]) + if err != nil { + return err + } + + _, err = f.WriteString("(") + if err != nil { + return err + } + + for i, param := range fn.Sig.Params[1:] { + _, err = f.WriteString(convertCffTypeToCType(param)) + if err != nil { + return err + } + + _, err = f.WriteString(" ") + if err != nil { + return err + } + + _, err = f.WriteString(fn.Params[i+1].Name()) + if err != nil { + return err + } + + if i != len(fn.Sig.Params)-2 { + _, err = f.WriteString(", ") + if err != nil { + return err + } + } + } + + _, err = f.WriteString(")") + if err != nil { + return err + } + + _, err = f.WriteString(";\n") + if err != nil { + return err + } + } + + _, err = f.WriteString("};\n") + if err != nil { + return err + } + } + _, err = f.WriteString("#endif\n") if err != nil { return err diff --git a/src/lib/compiler/compiler.go b/src/lib/compiler/compiler.go index 524f8c1..ad1b257 100644 --- a/src/lib/compiler/compiler.go +++ b/src/lib/compiler/compiler.go @@ -148,9 +148,9 @@ func (c *Compiler) ImportAll(path string, ctx *Context) error { if s.Export.FunctionDefinition != nil { var params []*ir.Param for _, p := range s.Export.FunctionDefinition.Parameters { - params = append(params, ir.NewParam(p.Name, ctx.stringToType(p.Type))) + params = append(params, ir.NewParam(p.Name, ctx.StringToType(p.Type))) } - fn := c.Module.NewFunc(s.Export.FunctionDefinition.Name, ctx.stringToType(s.Export.FunctionDefinition.ReturnType), params...) + fn := c.Module.NewFunc(s.Export.FunctionDefinition.Name, ctx.StringToType(s.Export.FunctionDefinition.ReturnType), params...) ctx.SymbolTable[s.Export.FunctionDefinition.Name] = fn } else if s.Export.ClassDefinition != nil { cStruct := types.NewStruct() @@ -159,19 +159,19 @@ func (c *Compiler) ImportAll(path string, ctx *Context) error { ctx.structNames[cStruct] = s.Export.ClassDefinition.Name for _, st := range s.Export.ClassDefinition.Body { if st.FieldDefinition != nil { - cStruct.Fields = append(cStruct.Fields, ctx.stringToType(st.FieldDefinition.Type)) + cStruct.Fields = append(cStruct.Fields, ctx.StringToType(st.FieldDefinition.Type)) ctx.Compiler.StructFields[s.Export.ClassDefinition.Name] = append(ctx.Compiler.StructFields[s.Export.ClassDefinition.Name], st.FieldDefinition) } else if st.FunctionDefinition != nil { f := st.FunctionDefinition var params []*ir.Param params = append(params, ir.NewParam("this", types.NewPointer(cStruct))) for _, arg := range f.Parameters { - params = append(params, ir.NewParam(arg.Name, ctx.stringToType(arg.Type))) + params = append(params, ir.NewParam(arg.Name, ctx.StringToType(arg.Type))) } - fn := ctx.Module.NewFunc(s.Export.ClassDefinition.Name+"."+f.Name, ctx.stringToType(f.ReturnType), params...) + fn := ctx.Module.NewFunc(s.Export.ClassDefinition.Name+"."+f.Name, ctx.StringToType(f.ReturnType), params...) fn.Sig.Variadic = false - fn.Sig.RetType = ctx.stringToType(f.ReturnType) + fn.Sig.RetType = ctx.StringToType(f.ReturnType) ctx.SymbolTable[s.Export.ClassDefinition.Name+"."+f.Name] = fn } @@ -204,9 +204,9 @@ func (c *Compiler) ImportAs(path string, symbols map[string]string, ctx *Context if newname, ok := symbols[s.Export.FunctionDefinition.Name]; ok { var params []*ir.Param for _, p := range s.Export.FunctionDefinition.Parameters { - params = append(params, ir.NewParam(p.Name, ctx.stringToType(p.Type))) + params = append(params, ir.NewParam(p.Name, ctx.StringToType(p.Type))) } - fn := c.Module.NewFunc(s.Export.FunctionDefinition.Name, ctx.stringToType(s.Export.FunctionDefinition.ReturnType), params...) + fn := c.Module.NewFunc(s.Export.FunctionDefinition.Name, ctx.StringToType(s.Export.FunctionDefinition.ReturnType), params...) if newname == "" { newname = s.Export.FunctionDefinition.Name } @@ -220,13 +220,13 @@ func (c *Compiler) ImportAs(path string, symbols map[string]string, ctx *Context cStruct := types.NewStruct() for _, st := range s.Export.ClassDefinition.Body { if st.FieldDefinition != nil { - cStruct.Fields = append(cStruct.Fields, ctx.stringToType(st.FieldDefinition.Type)) + cStruct.Fields = append(cStruct.Fields, ctx.StringToType(st.FieldDefinition.Type)) } else if st.FunctionDefinition != nil { var params []*ir.Param for _, p := range st.FunctionDefinition.Parameters { - params = append(params, ir.NewParam(p.Name, ctx.stringToType(p.Type))) + params = append(params, ir.NewParam(p.Name, ctx.StringToType(p.Type))) } - fn := c.Module.NewFunc(st.FunctionDefinition.Name, ctx.stringToType(st.FunctionDefinition.ReturnType), params...) + fn := c.Module.NewFunc(st.FunctionDefinition.Name, ctx.StringToType(st.FunctionDefinition.ReturnType), params...) ctx.SymbolTable[newname+"."+st.FunctionDefinition.Name] = fn } } diff --git a/src/lib/compiler/expressions.go b/src/lib/compiler/expressions.go index 03c2fe9..c9e03fc 100644 --- a/src/lib/compiler/expressions.go +++ b/src/lib/compiler/expressions.go @@ -297,8 +297,8 @@ func (ctx *Context) compileSubIdentifier(fieldType types.Type, pointer value.Val if field == nil { return nil, nil, false, posError(sub.Pos, "Field %s not found in struct %s", sub.Name, elemtypename) } - fieldPtr := ctx.NewGetElementPtr(ctx.stringToType(field.Type), pointer, constant.NewInt(types.I32, int64(nfield))) - return ctx.compileSubIdentifier(ctx.stringToType(field.Type), fieldPtr, sub.Sub) + fieldPtr := ctx.NewGetElementPtr(ctx.StringToType(field.Type), pointer, constant.NewInt(types.I32, int64(nfield))) + return ctx.compileSubIdentifier(ctx.StringToType(field.Type), fieldPtr, sub.Sub) } return fieldType, pointer, false, nil } diff --git a/src/lib/compiler/statements.go b/src/lib/compiler/statements.go index adb4979..1c9e803 100644 --- a/src/lib/compiler/statements.go +++ b/src/lib/compiler/statements.go @@ -76,11 +76,11 @@ func (ctx *Context) compileExternalFunction(v *parser.ExternalFunctionDefinition if v.ReturnType == "" { retType = types.Void } else { - retType = ctx.stringToType(v.ReturnType) + retType = ctx.StringToType(v.ReturnType) } var args []*ir.Param for _, arg := range v.Parameters { - args = append(args, ir.NewParam(arg.Name, ctx.stringToType(arg.Type))) + args = append(args, ir.NewParam(arg.Name, ctx.StringToType(arg.Type))) } fn := ctx.Module.NewFunc(v.Name, retType, args...) @@ -88,9 +88,9 @@ func (ctx *Context) compileExternalFunction(v *parser.ExternalFunctionDefinition } func (ctx *Context) compileExternalVariable(v *parser.ExternalVariableDefinition) { - globalV := ctx.Module.NewGlobal(v.Name, ctx.stringToType(v.Type)) + globalV := ctx.Module.NewGlobal(v.Name, ctx.StringToType(v.Type)) globalV.ExternallyInitialized = true - globalV.Init = constant.NewZeroInitializer(ctx.stringToType(v.Type)) + globalV.Init = constant.NewZeroInitializer(ctx.StringToType(v.Type)) fmt.Println(globalV.Type()) ctx.vars[v.Name] = globalV } @@ -98,7 +98,7 @@ func (ctx *Context) compileExternalVariable(v *parser.ExternalVariableDefinition func (ctx *Context) compileVariableDefinition(v *parser.VariableDefinition) (Name string, Type types.Type, Value value.Value, Err error) { // If there is no assignment, create an uninitialized variable if v.Assignment == nil { - valType := ctx.stringToType(v.Type) + valType := ctx.StringToType(v.Type) alloc := ctx.NewAlloca(valType) ctx.NewStore(constant.NewZeroInitializer(valType), alloc) ctx.vars[v.Name] = alloc @@ -151,12 +151,12 @@ func (ctx *Context) compileAssignment(a *parser.Assignment) (Name string, Value func (ctx *Context) compileFunctionDefinition(f *parser.FunctionDefinition) (Name string, ReturnType types.Type, Args []*ir.Param, err error) { var params []*ir.Param for _, arg := range f.Parameters { - params = append(params, ir.NewParam(arg.Name, ctx.stringToType(arg.Type))) + params = append(params, ir.NewParam(arg.Name, ctx.StringToType(arg.Type))) } - fn := ctx.Module.NewFunc(f.Name, ctx.stringToType(f.ReturnType), params...) + fn := ctx.Module.NewFunc(f.Name, ctx.StringToType(f.ReturnType), params...) fn.Sig.Variadic = f.Variadic - fn.Sig.RetType = ctx.stringToType(f.ReturnType) + fn.Sig.RetType = ctx.StringToType(f.ReturnType) block := fn.NewBlock("") nctx := NewContext(block, ctx.Compiler) ctx.SymbolTable[f.Name] = fn @@ -168,14 +168,14 @@ func (ctx *Context) compileFunctionDefinition(f *parser.FunctionDefinition) (Nam } } if nctx.Term == nil { - if ctx.stringToType(f.ReturnType).Equal(types.Void) { + if ctx.StringToType(f.ReturnType).Equal(types.Void) { nctx.NewRet(nil) } else { return "", nil, nil, posError(f.Pos, "Function `%s` does not return a value", f.Name) } } - return f.Name, ctx.stringToType(f.ReturnType), params, nil + return f.Name, ctx.StringToType(f.ReturnType), params, nil } func (ctx *Context) compileClassDefinition(c *parser.ClassDefinition) (Name string, TypeDef *types.StructType, Methods []ir.Func, err error) { @@ -186,11 +186,13 @@ func (ctx *Context) compileClassDefinition(c *parser.ClassDefinition) (Name stri for _, s := range c.Body { if s.FieldDefinition != nil { - classType.Fields = append(classType.Fields, ctx.stringToType(s.FieldDefinition.Type)) + classType.Fields = append(classType.Fields, ctx.StringToType(s.FieldDefinition.Type)) ctx.Compiler.StructFields[c.Name] = append(ctx.Compiler.StructFields[c.Name], s.FieldDefinition) } else if s.FunctionDefinition != nil { err := ctx.compileClassMethodDefinition(s.FunctionDefinition, c.Name, classType) - return "", nil, []ir.Func{}, err + if err != nil { + return "", nil, []ir.Func{}, err + } } } @@ -201,12 +203,12 @@ func (ctx *Context) compileClassMethodDefinition(f *parser.FunctionDefinition, c var params []*ir.Param params = append(params, ir.NewParam("this", types.NewPointer(ctype))) for _, arg := range f.Parameters { - params = append(params, ir.NewParam(arg.Name, ctx.stringToType(arg.Type))) + params = append(params, ir.NewParam(arg.Name, ctx.StringToType(arg.Type))) } - fn := ctx.Module.NewFunc(cname+"."+f.Name, ctx.stringToType(f.ReturnType), params...) + fn := ctx.Module.NewFunc(cname+"."+f.Name, ctx.StringToType(f.ReturnType), params...) fn.Sig.Variadic = false - fn.Sig.RetType = ctx.stringToType(f.ReturnType) + fn.Sig.RetType = ctx.StringToType(f.ReturnType) block := fn.NewBlock("") nctx := NewContext(block, ctx.Compiler) for _, stmt := range f.Body { @@ -216,7 +218,7 @@ func (ctx *Context) compileClassMethodDefinition(f *parser.FunctionDefinition, c } } if nctx.Term == nil { - if ctx.stringToType(f.ReturnType).Equal(types.Void) { + if ctx.StringToType(f.ReturnType).Equal(types.Void) { nctx.NewRet(nil) } else { cli.Exit(color.RedString("Error: Method `%s` of class `%s` does not return a value", f.Name, cname), 1) diff --git a/src/lib/compiler/utils.go b/src/lib/compiler/utils.go index ed9e238..d273f79 100644 --- a/src/lib/compiler/utils.go +++ b/src/lib/compiler/utils.go @@ -13,7 +13,7 @@ func posError(pos lexer.Position, message string, args ...interface{}) error { return cli.Exit(color.RedString("%s at %s:%d:%d", fmt.Sprintf(message, args...), pos.Filename, pos.Line, pos.Column), 1) } -func (ctx *Context) stringToType(name string) types.Type { +func (ctx *Context) StringToType(name string) types.Type { switch name { // Standard types case "int":