feat: add stdlib IO and extern function support
- Add stdlib/io.c with PrintLine, Print, PrintInt, PrintFloat, PrintBool, ReadLine - Support extern function declarations (functions without body) - Generate C forward declarations for extern functions - Map Bux type names (String, int, etc.) to C types in codegen - Update build system to copy all stdlib files - Hello World example works: prints 'Hello, Bux!'
This commit is contained in:
+35
-1
@@ -64,7 +64,24 @@ proc typeToC*(typ: Type): string =
|
||||
if typ.inner.len > 0:
|
||||
return typeToC(typ.inner[0]) & "*"
|
||||
return "void*"
|
||||
of tkNamed: return typ.name
|
||||
of tkNamed:
|
||||
# Map common Bux type names to C types
|
||||
case typ.name
|
||||
of "String", "str": return "const char*"
|
||||
of "int": return "int"
|
||||
of "int8": return "int8_t"
|
||||
of "int16": return "int16_t"
|
||||
of "int32": return "int32_t"
|
||||
of "int64": return "int64_t"
|
||||
of "uint": return "unsigned int"
|
||||
of "uint8": return "uint8_t"
|
||||
of "uint16": return "uint16_t"
|
||||
of "uint32": return "uint32_t"
|
||||
of "uint64": return "uint64_t"
|
||||
of "float32": return "float"
|
||||
of "float64": return "double"
|
||||
of "bool": return "bool"
|
||||
else: return typ.name
|
||||
of tkTuple: return "void*" # TODO: proper tuple struct
|
||||
of tkFunc: return "void*" # TODO: function pointer
|
||||
else: return "int"
|
||||
@@ -344,6 +361,16 @@ proc emitEnum*(be: var CBackend, name: string, variants: seq[string]) =
|
||||
be.emitLine(&"}} {name};")
|
||||
be.emitLine("")
|
||||
|
||||
proc emitExternDecl*(be: var CBackend, efunc: HirFunc) =
|
||||
let retType = typeToC(efunc.retType)
|
||||
var params: seq[string] = @[]
|
||||
for p in efunc.params:
|
||||
params.add(&"{typeToC(p.typ)} {p.name}")
|
||||
if params.len == 0:
|
||||
params.add("void")
|
||||
let paramsStr = params.join(", ")
|
||||
be.emitLine(&"extern {retType} {efunc.name}({paramsStr});")
|
||||
|
||||
proc emitModule*(be: var CBackend, module: HirModule): string =
|
||||
# Header
|
||||
be.emitLine("/* Generated by Bux Compiler */")
|
||||
@@ -360,6 +387,13 @@ proc emitModule*(be: var CBackend, module: HirModule): string =
|
||||
if module.structs.len > 0:
|
||||
be.emitLine("")
|
||||
|
||||
# Extern function declarations
|
||||
if module.externFuncs.len > 0:
|
||||
be.emitLine("/* Extern function declarations */")
|
||||
for ef in module.externFuncs:
|
||||
be.emitExternDecl(ef)
|
||||
be.emitLine("")
|
||||
|
||||
# Struct definitions
|
||||
for s in module.structs:
|
||||
be.emitStruct(s.name, s.fields)
|
||||
|
||||
+31
-16
@@ -256,30 +256,45 @@ proc cmdBuild*(args: seq[string], opts: GlobalOptions): int =
|
||||
let cFile = buildDir / "main.c"
|
||||
writeFile(cFile, allCCode)
|
||||
|
||||
# Copy runtime
|
||||
# Copy runtime and stdlib files
|
||||
let runtimeDst = buildDir / "runtime.c"
|
||||
var runtimeFound = false
|
||||
# Search in multiple locations
|
||||
let searchPaths = @[
|
||||
getAppDir() / ".." / "stdlib" / "runtime.c",
|
||||
getAppDir() / "stdlib" / "runtime.c",
|
||||
root / "stdlib" / "runtime.c",
|
||||
root / "stdlib_runtime.c",
|
||||
"/home/ziko/z-git/bux/bux/stdlib/runtime.c", # TODO: make this configurable
|
||||
let ioDst = buildDir / "io.c"
|
||||
var stdlibDir = ""
|
||||
# Search for stdlib directory
|
||||
let stdlibSearchPaths = @[
|
||||
getAppDir() / ".." / "stdlib",
|
||||
getAppDir() / "stdlib",
|
||||
root / "stdlib",
|
||||
"/home/ziko/z-git/bux/bux/stdlib", # TODO: make this configurable
|
||||
]
|
||||
for runtimePath in searchPaths:
|
||||
if fileExists(runtimePath):
|
||||
copyFile(runtimePath, runtimeDst)
|
||||
runtimeFound = true
|
||||
for path in stdlibSearchPaths:
|
||||
if dirExists(path):
|
||||
stdlibDir = path
|
||||
break
|
||||
if not runtimeFound:
|
||||
printError("runtime.c not found (searched in stdlib/, build/, and project root)", useColor)
|
||||
if stdlibDir == "":
|
||||
printError("stdlib directory not found", useColor)
|
||||
return 1
|
||||
|
||||
# Copy runtime.c
|
||||
let runtimeSrc = stdlibDir / "runtime.c"
|
||||
if fileExists(runtimeSrc):
|
||||
copyFile(runtimeSrc, runtimeDst)
|
||||
else:
|
||||
printError("runtime.c not found in stdlib", useColor)
|
||||
return 1
|
||||
|
||||
# Copy io.c
|
||||
let ioSrc = stdlibDir / "io.c"
|
||||
if fileExists(ioSrc):
|
||||
copyFile(ioSrc, ioDst)
|
||||
else:
|
||||
printError("io.c not found in stdlib", useColor)
|
||||
return 1
|
||||
|
||||
# Compile with cc
|
||||
let outputName = if man.name != "": man.name else: "bux_out"
|
||||
let outputFile = buildDir / outputName
|
||||
let ccCmd = &"cc -o {outputFile} {cFile} {runtimeDst} -lm 2>&1"
|
||||
let ccCmd = &"cc -o {outputFile} {cFile} {runtimeDst} {ioDst} -lm 2>&1"
|
||||
if opts.verbose:
|
||||
printInfo(&"running: {ccCmd}", useColor)
|
||||
let (output, exitCode) = execCmdEx(ccCmd)
|
||||
|
||||
@@ -126,6 +126,7 @@ type
|
||||
|
||||
HirModule* = object
|
||||
funcs*: seq[HirFunc]
|
||||
externFuncs*: seq[HirFunc] # Functions declared with extern (no body)
|
||||
structs*: seq[tuple[name: string, fields: seq[tuple[name: string, typ: Type]]]]
|
||||
enums*: seq[tuple[name: string, variants: seq[string]]]
|
||||
consts*: seq[tuple[name: string, typ: Type, value: HirNode]]
|
||||
|
||||
+7
-2
@@ -420,6 +420,7 @@ proc lowerFunc*(ctx: var LowerCtx, decl: Decl): HirFunc =
|
||||
proc lowerModule*(module: Module, sema: Sema): HirModule =
|
||||
var ctx = initLowerCtx(module, sema)
|
||||
var funcs: seq[HirFunc] = @[]
|
||||
var externFuncs: seq[HirFunc] = @[]
|
||||
var structs: seq[tuple[name: string, fields: seq[tuple[name: string, typ: Type]]]] = @[]
|
||||
var enums: seq[tuple[name: string, variants: seq[string]]] = @[]
|
||||
var consts: seq[tuple[name: string, typ: Type, value: HirNode]] = @[]
|
||||
@@ -427,7 +428,11 @@ proc lowerModule*(module: Module, sema: Sema): HirModule =
|
||||
for decl in module.items:
|
||||
case decl.kind
|
||||
of dkFunc:
|
||||
funcs.add(ctx.lowerFunc(decl))
|
||||
if decl.declFuncBody != nil:
|
||||
funcs.add(ctx.lowerFunc(decl))
|
||||
else:
|
||||
# Extern function (no body)
|
||||
externFuncs.add(ctx.lowerFunc(decl))
|
||||
of dkImpl:
|
||||
for methodDecl in decl.declImplMethods:
|
||||
if methodDecl.kind == dkFunc:
|
||||
@@ -461,4 +466,4 @@ proc lowerModule*(module: Module, sema: Sema): HirModule =
|
||||
consts.add((decl.declConstName, typ, value))
|
||||
else: discard
|
||||
|
||||
result = HirModule(funcs: funcs, structs: structs, enums: enums, consts: consts)
|
||||
result = HirModule(funcs: funcs, externFuncs: externFuncs, structs: structs, enums: enums, consts: consts)
|
||||
|
||||
Reference in New Issue
Block a user