package build import ( "fmt" "strconv" "git.akyoto.dev/cli/q/src/build/arch/x64" "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/config" "git.akyoto.dev/cli/q/src/build/token" "git.akyoto.dev/go/color/ansi" ) // Function represents a function. type Function struct { Name string Head token.List Body token.List Assembler asm.Assembler } // Compile turns a function into machine code. func (f *Function) Compile() { if config.Verbose { ansi.Underline.Println(f.Name) } for _, line := range f.Lines() { if config.Verbose { fmt.Println("[line]", line) } if len(line) == 0 { continue } if line[0].Kind == token.Identifier && line[0].Text() == "syscall" { paramTokens := line[2 : len(line)-1] start := 0 i := 0 var parameters []token.List for i < len(paramTokens) { if paramTokens[i].Kind == token.Separator { parameters = append(parameters, paramTokens[start:i]) start = i + 1 } i++ } if i != start { parameters = append(parameters, paramTokens[start:i]) } for i, list := range parameters { if list[0].Kind == token.Number { numAsText := list[0].Text() n, _ := strconv.Atoi(numAsText) f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n)) } } f.Assembler.Syscall() } } } // Lines returns the lines in the function body. func (f *Function) Lines() []token.List { var ( lines []token.List start = 0 i = 0 ) for i < len(f.Body) { if f.Body[i].Kind == token.NewLine { lines = append(lines, f.Body[start:i]) start = i + 1 } i++ } if i != start { lines = append(lines, f.Body[start:i]) } return lines } // String returns the function name. func (f *Function) String() string { return f.Name }