From 7e069bb00a9b09de89c25be4bd3fe5a075291dfc Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Fri, 22 May 2026 09:30:46 +0200 Subject: [PATCH] format code and update makefile --- Makefile | 9 +- src/astgen.cpp | 140 ++++++++++++-------------- src/codegen.cpp | 4 +- src/codegen.h | 7 +- src/comptime.cpp | 192 ++++++++++++++++-------------------- src/comptime.h | 33 +++---- src/main.cpp | 82 ++++++++------- src/mangling.h | 3 +- src/parser.cpp | 27 +++-- tests/cpp/test_comptime.cpp | 49 +++++---- tests/cpp/test_print.cpp | 8 +- 11 files changed, 261 insertions(+), 293 deletions(-) diff --git a/Makefile b/Makefile index 7a970f9..1371c72 100644 --- a/Makefile +++ b/Makefile @@ -171,7 +171,14 @@ test-comptime: build @clang++ -o $(OUT)/comptime_tests $(OUT)/test_comptime.o $(OUT)/comptime.o $(OUT)/diagnostics.o @$(OUT)/comptime_tests -test: test-unit test-init test-abi test-codegen-errors test-jir test-diagnostics test-decl test-analyzer test-comptime +test-print: build + @echo "" + @echo "Building and running @-emit cfn-print end-to-end tests..." + @clang++ -c ./tests/cpp/test_print.cpp -o $(OUT)/test_print.o `$(LLVM_CONFIG) --cxxflags` -fexceptions $(OPTFLAGS) + @clang++ -o $(OUT)/print_tests $(OUT)/test_print.o + @$(OUT)/print_tests + +test: test-unit test-init test-abi test-codegen-errors test-jir test-diagnostics test-decl test-analyzer test-comptime test-print test-release: test test-unit-release fmt: format diff --git a/src/astgen.cpp b/src/astgen.cpp index 51e4f14..a8cf40b 100644 --- a/src/astgen.cpp +++ b/src/astgen.cpp @@ -47,9 +47,10 @@ struct LoopFrame { // order so drop calls are emitted in REVERSE order at scope exit. struct DropTrack { std::string varName; - JirRef slot; // alloca for the variable - TypeIdx type; // source-level type - std::string llvmFnName; // canonical drop fn — FQN like `T.drop` / `m.T.drop` + JirRef slot; // alloca for the variable + TypeIdx type; // source-level type + std::string + llvmFnName; // canonical drop fn — FQN like `T.drop` / `m.T.drop` }; struct AstGenCtx { @@ -662,8 +663,8 @@ static void astgenVarDecl(AstGenCtx &gctx, const AstNode &n) { if (r != kNoType) return resolveForCmp(r); } if (k.kind == TypeKind::Named) { - const std::string &nm = gctx.ctx.getStringPool().get( - static_cast(k.a)); + const std::string &nm = + gctx.ctx.getStringPool().get(static_cast(k.a)); TypeIdx a = gctx.ctx.lookupTypeAlias(nm); if (a != kNoType) return resolveForCmp(a); // 3+ segment chain through module re-exports — collapse @@ -755,8 +756,7 @@ static JirRef astgenVariable(AstGenCtx &gctx, const AstNode &n, // (the local-lookup above runs first); module consts and // functions are checked after, so a comp-bound name takes // precedence over a same-named module const. - if (const jam::ComptimeValue *cv = - gctx.ctx.lookupCurrentCompSubst(name)) { + if (const jam::ComptimeValue *cv = gctx.ctx.lookupCurrentCompSubst(name)) { switch (cv->kind) { case jam::ComptimeValue::Kind::Int: { JirInst ic{}; @@ -764,7 +764,7 @@ static JirRef astgenVariable(AstGenCtx &gctx, const AstNode &n, ic.a = static_cast(cv->intVal.bits & 0xFFFFFFFFu); ic.b = static_cast(cv->intVal.bits >> 32); ic.ty = gctx.ctx.getTypePool().internInt(cv->intVal.width, - cv->intVal.isSigned); + cv->intVal.isSigned); return emit(gctx, ic); } case jam::ComptimeValue::Kind::Bool: { @@ -804,8 +804,7 @@ static JirRef astgenVariable(AstGenCtx &gctx, const AstNode &n, case jam::ComptimeValue::Kind::Aggregate: case jam::ComptimeValue::Kind::None: return recoverHere( - gctx, - "comp param `" + name + "` has no runtime lowering yet", + gctx, "comp param `" + name + "` has no runtime lowering yet", kNoType); } } @@ -3431,7 +3430,7 @@ static void ensureDprintfForCfn(AstGenCtx &gctx) { JamTypeRef i8PtrType = JamLLVMPointerType(gctx.ctx.getInt8Type(), 0); JamTypeRef paramTypes[2] = {gctx.ctx.getInt32Type(), i8PtrType}; JamTypeRef ft = JamLLVMFunctionType(gctx.ctx.getInt32Type(), paramTypes, 2, - /*isVarArgs=*/true); + /*isVarArgs=*/true); JamFunctionRef pf = JamLLVMAddFunction(gctx.ctx.getModule(), "dprintf", ft); JamLLVMApplyDefaultFnAttrs(pf, /*isExtern=*/true); } @@ -3440,7 +3439,7 @@ static void ensureDprintfForCfn(AstGenCtx &gctx) { // format string. Used by the per-type interp lowering and by // emitPutByte for the "%c" case. static void emitDprintfSingleArg(AstGenCtx &gctx, JirRef fdRef, - const char *fmtSpec, JirRef arg) { + const char *fmtSpec, JirRef arg) { TypeIdx sliceTy = gctx.ctx.getTypePool().intern( TypeKey{TypeKind::Slice, 0, 0, BuiltinType::U8, 0}); TypeIdx u8PtrTy = gctx.ctx.getTypePool().intern( @@ -3458,8 +3457,8 @@ static void emitDprintfSingleArg(AstGenCtx &gctx, JirRef fdRef, fp.ty = u8PtrTy; JirRef fmtPtr = emit(gctx, fp); std::vector pp = {3, static_cast(fdRef), - static_cast(fmtPtr), - static_cast(arg)}; + static_cast(fmtPtr), + static_cast(arg)}; JirExtraIdx pe = gctx.jfn.pushExtra(pp.data(), pp.size()); JirInst c{}; c.tag = JirTag::Call; @@ -3483,8 +3482,8 @@ static JirRef literalI32(AstGenCtx &gctx, uint32_t value) { // identifier (only used for the diagnostic). The dispatcher widens / // extracts as needed and emits one dprintf call per piece. static void emitDprintfForValue(AstGenCtx &gctx, jam::Diagnostics &diags, - jam::SrcLoc loc, JirRef fdRef, JirRef val, - const std::string &name) { + jam::SrcLoc loc, JirRef fdRef, JirRef val, + const std::string &name) { TypeIdx ty = gctx.jfn.getInst(val).ty; const TypeKey &k = gctx.ctx.getTypePool().get(ty); switch (k.kind) { @@ -3499,8 +3498,7 @@ static void emitDprintfForValue(AstGenCtx &gctx, jam::Diagnostics &diags, ext.ty = BuiltinType::I64; wideRef = emit(gctx, ext); } - emitDprintfSingleArg(gctx, fdRef, isSigned ? "%lld" : "%llu", - wideRef); + emitDprintfSingleArg(gctx, fdRef, isSigned ? "%lld" : "%llu", wideRef); return; } case TypeKind::Float: { @@ -3565,9 +3563,8 @@ static void emitDprintfForValue(AstGenCtx &gctx, jam::Diagnostics &diags, fp.ty = u8PtrTy; JirRef fmtPtr = emit(gctx, fp); std::vector pp = { - 4, static_cast(fdRef), - static_cast(fmtPtr), static_cast(lnI32), - static_cast(ptr)}; + 4, static_cast(fdRef), static_cast(fmtPtr), + static_cast(lnI32), static_cast(ptr)}; JirExtraIdx pe = gctx.jfn.pushExtra(pp.data(), pp.size()); JirInst c{}; c.tag = JirTag::Call; @@ -3635,10 +3632,11 @@ static void emitDprintfForValue(AstGenCtx &gctx, jam::Diagnostics &diags, return; } default: - diags.error(loc, "@emit: local `" + name + "` has a type that's " - "not printable (only " - "int / float / bool / " - "slice supported)"); + diags.error(loc, "@emit: local `" + name + + "` has a type that's " + "not printable (only " + "int / float / bool / " + "slice supported)"); return; } } @@ -3651,13 +3649,11 @@ class CfnEmitter : public jam::CompEmitter { public: explicit CfnEmitter(AstGenCtx &gctx) : gctx_(gctx) {} - jam::ExecResult - handleAtCall(const std::string &name, - const std::vector &args, - jam::Diagnostics &diags, jam::SrcLoc loc) override { - if (name == "emitPutByte") { - return handlePutByte(args, diags, loc); - } + jam::ExecResult handleAtCall(const std::string &name, + const std::vector &args, + jam::Diagnostics &diags, + jam::SrcLoc loc) override { + if (name == "emitPutByte") { return handlePutByte(args, diags, loc); } if (name == "emitPrintLocalByRange") { return handlePrintLocalByRange(args, diags, loc); } @@ -3671,17 +3667,15 @@ class CfnEmitter : public jam::CompEmitter { private: AstGenCtx &gctx_; - jam::ExecResult - handlePutByte(const std::vector &args, - jam::Diagnostics &diags, jam::SrcLoc loc) { + jam::ExecResult handlePutByte(const std::vector &args, + jam::Diagnostics &diags, jam::SrcLoc loc) { if (args.size() != 2 || !args[0].isInt() || !args[1].isInt()) { - diags.error(loc, - "@emitPutByte expects (fd: i32, byte: u8)"); + diags.error(loc, "@emitPutByte expects (fd: i32, byte: u8)"); return jam::ExecResult::Error; } ensureDprintfForCfn(gctx_); - JirRef fdRef = literalI32(gctx_, - static_cast(args[0].asU64())); + JirRef fdRef = + literalI32(gctx_, static_cast(args[0].asU64())); JirInst byteI{}; byteI.tag = JirTag::Int; byteI.a = static_cast(args[1].asU64() & 0xFFu); @@ -3693,12 +3687,11 @@ class CfnEmitter : public jam::CompEmitter { jam::ExecResult handlePrintLocalByRange(const std::vector &args, - jam::Diagnostics &diags, jam::SrcLoc loc) { + jam::Diagnostics &diags, jam::SrcLoc loc) { if (args.size() != 4 || !args[0].isInt() || !args[1].isStr() || !args[2].isInt() || !args[3].isInt()) { - diags.error(loc, - "@emitPrintLocalByRange expects " - "(fd: i32, fmt: str, start: u32, end: u32)"); + diags.error(loc, "@emitPrintLocalByRange expects " + "(fd: i32, fmt: str, start: u32, end: u32)"); return jam::ExecResult::Error; } uint32_t fd = static_cast(args[0].asU64()); @@ -3707,9 +3700,8 @@ class CfnEmitter : public jam::CompEmitter { uint32_t start = static_cast(args[2].asU64()); uint32_t end = static_cast(args[3].asU64()); if (start > end || end > fmtStr.length()) { - diags.error(loc, - "@emitPrintLocalByRange: range out of bounds " - "for the format string"); + diags.error(loc, "@emitPrintLocalByRange: range out of bounds " + "for the format string"); return jam::ExecResult::Error; } std::string name = fmtStr.substr(start, end - start); @@ -3739,12 +3731,11 @@ class CfnEmitter : public jam::CompEmitter { // dprintf. jam::ExecResult handleWriteBytes(const std::vector &args, - jam::Diagnostics &diags, jam::SrcLoc loc) { + jam::Diagnostics &diags, jam::SrcLoc loc) { if (args.size() != 4 || !args[0].isInt() || !args[1].isStr() || !args[2].isInt() || !args[3].isInt()) { - diags.error(loc, - "@emitWriteBytes expects " - "(fd: i32, fmt: str, start: u32, end: u32)"); + diags.error(loc, "@emitWriteBytes expects " + "(fd: i32, fmt: str, start: u32, end: u32)"); return jam::ExecResult::Error; } uint32_t fd = static_cast(args[0].asU64()); @@ -3753,9 +3744,8 @@ class CfnEmitter : public jam::CompEmitter { uint32_t start = static_cast(args[2].asU64()); uint32_t end = static_cast(args[3].asU64()); if (start > end || end > fmtStr.length()) { - diags.error(loc, - "@emitWriteBytes: range out of bounds " - "for the format string"); + diags.error(loc, "@emitWriteBytes: range out of bounds " + "for the format string"); return jam::ExecResult::Error; } if (start == end) { @@ -3764,8 +3754,8 @@ class CfnEmitter : public jam::CompEmitter { return jam::ExecResult::Continue; } ensureDprintfForCfn(gctx_); - StringIdx litId = gctx_.ctx.getStringPool().intern( - fmtStr.substr(start, end - start)); + StringIdx litId = + gctx_.ctx.getStringPool().intern(fmtStr.substr(start, end - start)); TypeIdx sliceTy = gctx_.ctx.getTypePool().intern( TypeKey{TypeKind::Slice, 0, 0, BuiltinType::U8, 0}); TypeIdx u8PtrTy = gctx_.ctx.getTypePool().intern( @@ -3826,7 +3816,7 @@ class CfnEmitter : public jam::CompEmitter { // how `std.fmt.print` lowers to a sequence of write calls inside the // user's main() rather than inside print's own LLVM function. static JirRef astgenCompTimeFnCall(AstGenCtx &gctx, const AstNode &n, - const FunctionAST *fn) { + const FunctionAST *fn) { const NodeStore &ns = gctx.ctx.getNodeStore(); ExtraIdx argsExtra = static_cast(n.rhs); uint32_t argCount = ns.getExtra(argsExtra); @@ -3842,7 +3832,7 @@ static JirRef astgenCompTimeFnCall(AstGenCtx &gctx, const AstNode &n, // Evaluate each arg at compile time and bind to the param name. jam::ComptimeEvaluator ev(ns, gctx.ctx.getStringPool(), - gctx.ctx.getTypePool()); + gctx.ctx.getTypePool()); jam::ComptimeScope outer; jam::Diagnostics &diags = gctx.ctx.diagnostics(); jam::SrcLoc loc{gctx.ctx.currentFile(), 0}; @@ -3868,17 +3858,17 @@ static JirRef astgenCompTimeFnCall(AstGenCtx &gctx, const AstNode &n, uint32_t iterCounter = 0; jam::ComptimeValue returned; std::vector bodyVec(fn->Body.begin(), fn->Body.end()); - jam::ExecResult r = ev.execBlock(bodyVec.data(), bodyVec.size(), outer, - iterCounter, - jam::ComptimeEvaluator::kDefaultIterCap, - returned, diags, loc); + jam::ExecResult r = ev.execBlock( + bodyVec.data(), bodyVec.size(), outer, iterCounter, + jam::ComptimeEvaluator::kDefaultIterCap, returned, diags, loc); ev.clearCallContext(); if (r == jam::ExecResult::Error || r == jam::ExecResult::IterationCap) { // Diagnostic already pushed; return a poison so the rest of // the caller still gets analyzed. return recoverHere(gctx, - "cfn `" + fn->Name + "` failed during compile-" - "time evaluation", + "cfn `" + fn->Name + + "` failed during compile-" + "time evaluation", kNoType); } // cfn returns void in v1; the value (if any) is discarded for now. @@ -3886,14 +3876,13 @@ static JirRef astgenCompTimeFnCall(AstGenCtx &gctx, const AstNode &n, } static JirRef astgenCompInstantiatedCall(AstGenCtx &gctx, const AstNode &n, - const FunctionAST *fn) { + const FunctionAST *fn) { const NodeStore &ns = gctx.ctx.getNodeStore(); ExtraIdx argsExtra = static_cast(n.rhs); uint32_t argCount = ns.getExtra(argsExtra); - jam::ComptimeEvaluator ev(gctx.ctx.getNodeStore(), - gctx.ctx.getStringPool(), - gctx.ctx.getTypePool()); + jam::ComptimeEvaluator ev(gctx.ctx.getNodeStore(), gctx.ctx.getStringPool(), + gctx.ctx.getTypePool()); jam::ComptimeScope scope; std::unordered_map compSubst; std::vector runtimeArgs; @@ -3932,8 +3921,7 @@ static JirRef astgenCompInstantiatedCall(AstGenCtx &gctx, const AstNode &n, case jam::ComptimeValue::Kind::Type: { const TypeKey &tk = gctx.ctx.getTypePool().get(v.typeVal); if (tk.kind == TypeKind::Int) { - mangleSuffix += - (tk.b ? "i" : "u") + std::to_string(tk.a); + mangleSuffix += (tk.b ? "i" : "u") + std::to_string(tk.a); } else if (tk.kind == TypeKind::Bool) { mangleSuffix += "bool"; } else { @@ -3970,12 +3958,11 @@ static JirRef astgenCompInstantiatedCall(AstGenCtx &gctx, const AstNode &n, fn->isCfn); clone = gctx.ctx.adoptInstantiatedFunction(std::move(cloned)); gctx.ctx.registerFunctionAST(instName, - const_cast(clone)); + const_cast(clone)); // Save the builder so we can return to the caller's insertion // point once the clone body's been emitted. - JamBasicBlockRef savedBB = - JamLLVMGetInsertBlock(gctx.ctx.getBuilder()); + JamBasicBlockRef savedBB = JamLLVMGetInsertBlock(gctx.ctx.getBuilder()); gctx.ctx.setCurrentCompSubst(compSubst); JirFunction jfn = astgenMetadata(*clone, gctx.ctx); @@ -4468,11 +4455,12 @@ static JirRef astgenCall(AstGenCtx &gctx, const AstNode &n) { if (fn != nullptr) { bool hasComp = false; for (const auto &p : fn->Args) { - if (p.isComp) { hasComp = true; break; } - } - if (hasComp) { - return astgenCompInstantiatedCall(gctx, n, fn); + if (p.isComp) { + hasComp = true; + break; + } } + if (hasComp) { return astgenCompInstantiatedCall(gctx, n, fn); } } if (fn == nullptr) { // Before erroring, try the fn-pointer-in-local-or-field paths. diff --git a/src/codegen.cpp b/src/codegen.cpp index ea64851..9b0c562 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -520,8 +520,8 @@ struct ChainWalkResult { const JamCodegenContext::ModuleNamespace *leaf; std::string lastSeg; }; -static ChainWalkResult -walkChain(const JamCodegenContext &ctx, const std::string &dotted) { +static ChainWalkResult walkChain(const JamCodegenContext &ctx, + const std::string &dotted) { std::vector segs = splitDotted(dotted); if (segs.size() < 3) return {nullptr, {}}; const auto *handle = ctx.getImportHandle(segs.front()); diff --git a/src/codegen.h b/src/codegen.h index 2db9898..954406a 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -314,8 +314,7 @@ class JamCodegenContext { // `getFunctionAST("handle.X")` lookup misses on a 3+ segment path // like `std.fmt.print`. Returns nullptr if any segment fails to // resolve to a Module → Module → ... → Function chain. - const FunctionAST * - resolveChainedFunction(const std::string &dotted) const; + const FunctionAST *resolveChainedFunction(const std::string &dotted) const; // Sibling of `resolveChainedFunction` for types. A type annotation // or struct literal like `w.lib.Point` parses into a Named type @@ -474,8 +473,8 @@ class JamCodegenContext { // for the rest of the compilation so its LLVM symbol stays // referenceable. Caller is expected to also `registerFunctionAST` // the clone so name-based lookups find it. - FunctionAST *adoptInstantiatedFunction( - std::unique_ptr cloned) const { + FunctionAST * + adoptInstantiatedFunction(std::unique_ptr cloned) const { FunctionAST *p = cloned.get(); instantiatedMethods_.push_back(std::move(cloned)); return p; diff --git a/src/comptime.cpp b/src/comptime.cpp index 96bdcbe..c4c5ae4 100644 --- a/src/comptime.cpp +++ b/src/comptime.cpp @@ -18,7 +18,7 @@ ComptimeValue ComptimeValue::makeNone() { } ComptimeValue ComptimeValue::makeInt(uint64_t bits, uint16_t width, - bool isSigned) { + bool isSigned) { ComptimeValue v; v.kind = Kind::Int; v.intVal.bits = bits; @@ -56,8 +56,7 @@ ComptimeValue ComptimeValue::makeType(TypeIdx t) { return v; } -ComptimeValue -ComptimeValue::makeAggregate(std::vector fields) { +ComptimeValue ComptimeValue::makeAggregate(std::vector fields) { ComptimeValue v; v.kind = Kind::Aggregate; v.aggFields = std::move(fields); @@ -120,12 +119,12 @@ const ComptimeValue *ComptimeScope::lookup(const std::string &name) const { // ─── Evaluator ────────────────────────────────────────────────── ComptimeEvaluator::ComptimeEvaluator(const NodeStore &nodes, - const StringPool &strings, - const TypePool &types) + const StringPool &strings, + const TypePool &types) : nodes_(nodes), strings_(strings), types_(types) {} ComptimeValue ComptimeEvaluator::eval(NodeIdx expr, - const ComptimeScope &scope) const { + const ComptimeScope &scope) const { if (expr == kNoNode) return ComptimeValue::makeNone(); const AstNode &n = nodes_.get(expr); switch (n.tag) { @@ -155,16 +154,13 @@ ComptimeValue ComptimeEvaluator::eval(NodeIdx expr, } } -ComptimeValue -ComptimeEvaluator::evalAtCall(const AstNode &n, - const ComptimeScope &scope) const { +ComptimeValue ComptimeEvaluator::evalAtCall(const AstNode &n, + const ComptimeScope &scope) const { // Type-arg single form (`@sizeOf(T)` / `@alignOf(T)`) doesn't // belong here — those produce a value the regular astgen path // turns into a JIR Int. From inside a cfn body, those still // return None (caller can do its own dispatch if it wants). - if ((n.flags & 1) == 0) { - return ComptimeValue::makeNone(); - } + if ((n.flags & 1) == 0) { return ComptimeValue::makeNone(); } // Expr-arg multi-form: rhs = ExtraIdx → [argCount, arg0, ...]. ExtraIdx extra = static_cast(n.rhs); @@ -176,10 +172,9 @@ ComptimeEvaluator::evalAtCall(const AstNode &n, ComptimeValue v = eval(argIdx, scope); if (v.isNone()) { if (diags_ != nullptr) { - diags_->error(loc_, - "@-emit argument must be a compile-time " - "constant (arg #" + - std::to_string(i) + ")"); + diags_->error(loc_, "@-emit argument must be a compile-time " + "constant (arg #" + + std::to_string(i) + ")"); } return ComptimeValue::makeNone(); } @@ -205,20 +200,20 @@ ComptimeEvaluator::evalAtCall(const AstNode &n, } ComptimeValue ComptimeEvaluator::evalRequired(NodeIdx expr, - const ComptimeScope &scope, - Diagnostics &diags, - SrcLoc loc) const { + const ComptimeScope &scope, + Diagnostics &diags, + SrcLoc loc) const { ComptimeValue v = eval(expr, scope); if (v.isNone()) { diags.error(std::move(loc), - "expression cannot be evaluated at compile time"); + "expression cannot be evaluated at compile time"); } return v; } ComptimeValue ComptimeEvaluator::evalNumberLit(const AstNode &n) const { - uint64_t bits = static_cast(n.lhs) | - (static_cast(n.rhs) << 32); + uint64_t bits = + static_cast(n.lhs) | (static_cast(n.rhs) << 32); bool isNeg = (n.flags & 1) != 0; bool isFloat = (n.flags & 2) != 0; if (isFloat) { @@ -233,8 +228,8 @@ ComptimeValue ComptimeEvaluator::evalNumberLit(const AstNode &n) const { // during folding. if (isNeg) { uint64_t magnitude = bits; - uint64_t signedBits = static_cast( - -static_cast(magnitude)); + uint64_t signedBits = + static_cast(-static_cast(magnitude)); return ComptimeValue::makeInt(signedBits, 64, /*isSigned=*/true); } return ComptimeValue::makeInt(bits, 64, /*isSigned=*/false); @@ -250,16 +245,15 @@ ComptimeValue ComptimeEvaluator::evalStringLit(const AstNode &n) const { ComptimeValue ComptimeEvaluator::evalVariable(const AstNode &n, - const ComptimeScope &scope) const { + const ComptimeScope &scope) const { const std::string &name = strings_.get(static_cast(n.lhs)); const ComptimeValue *v = scope.lookup(name); if (v == nullptr) return ComptimeValue::makeNone(); return *v; } -ComptimeValue -ComptimeEvaluator::evalUnaryOp(const AstNode &n, - const ComptimeScope &scope) const { +ComptimeValue ComptimeEvaluator::evalUnaryOp(const AstNode &n, + const ComptimeScope &scope) const { NodeIdx operand = static_cast(n.lhs); ComptimeValue v = eval(operand, scope); if (v.isNone()) return v; @@ -267,20 +261,24 @@ ComptimeEvaluator::evalUnaryOp(const AstNode &n, switch (op) { case UnaryOp::Neg: if (v.kind == ComptimeValue::Kind::Int) { - uint64_t neg = static_cast(-static_cast(v.asU64())); + uint64_t neg = + static_cast(-static_cast(v.asU64())); return ComptimeValue::makeInt(neg, v.intVal.width, true); } if (v.kind == ComptimeValue::Kind::Float) { - return ComptimeValue::makeFloat(-v.floatVal.value, v.floatVal.width); + return ComptimeValue::makeFloat(-v.floatVal.value, + v.floatVal.width); } return ComptimeValue::makeNone(); case UnaryOp::LogNot: - if (v.kind != ComptimeValue::Kind::Bool) return ComptimeValue::makeNone(); + if (v.kind != ComptimeValue::Kind::Bool) + return ComptimeValue::makeNone(); return ComptimeValue::makeBool(!v.boolVal); case UnaryOp::BitNot: - if (v.kind != ComptimeValue::Kind::Int) return ComptimeValue::makeNone(); + if (v.kind != ComptimeValue::Kind::Int) + return ComptimeValue::makeNone(); return ComptimeValue::makeInt(~v.intVal.bits, v.intVal.width, - v.intVal.isSigned); + v.intVal.isSigned); default: return ComptimeValue::makeNone(); } @@ -288,7 +286,7 @@ ComptimeEvaluator::evalUnaryOp(const AstNode &n, ComptimeValue ComptimeEvaluator::evalBinaryOp(const AstNode &n, - const ComptimeScope &scope) const { + const ComptimeScope &scope) const { NodeIdx lhsIdx = static_cast(n.lhs); NodeIdx rhsIdx = static_cast(n.rhs); BinOp op = static_cast(n.op); @@ -297,12 +295,14 @@ ComptimeEvaluator::evalBinaryOp(const AstNode &n, // and avoid evaluating the RHS when the LHS settles the answer. if (op == BinOp::LogAnd || op == BinOp::LogOr) { ComptimeValue l = eval(lhsIdx, scope); - if (l.kind != ComptimeValue::Kind::Bool) return ComptimeValue::makeNone(); + if (l.kind != ComptimeValue::Kind::Bool) + return ComptimeValue::makeNone(); bool lb = l.boolVal; if (op == BinOp::LogAnd && !lb) return ComptimeValue::makeBool(false); if (op == BinOp::LogOr && lb) return ComptimeValue::makeBool(true); ComptimeValue r = eval(rhsIdx, scope); - if (r.kind != ComptimeValue::Kind::Bool) return ComptimeValue::makeNone(); + if (r.kind != ComptimeValue::Kind::Bool) + return ComptimeValue::makeNone(); return ComptimeValue::makeBool(r.boolVal); } @@ -321,8 +321,8 @@ ComptimeEvaluator::evalBinaryOp(const AstNode &n, if (l.kind == ComptimeValue::Kind::Int && r.kind == ComptimeValue::Kind::Int) { bool isComparison = op == BinOp::Eq || op == BinOp::Ne || - op == BinOp::Lt || op == BinOp::Le || - op == BinOp::Gt || op == BinOp::Ge; + op == BinOp::Lt || op == BinOp::Le || + op == BinOp::Gt || op == BinOp::Ge; if (l.intVal.width != r.intVal.width) { if (!isComparison || l.intVal.isSigned != r.intVal.isSigned) { return ComptimeValue::makeNone(); @@ -355,7 +355,7 @@ ComptimeEvaluator::evalBinaryOp(const AstNode &n, if (sgn) { return ComptimeValue::makeInt( static_cast(static_cast(a) / - static_cast(b)), + static_cast(b)), w, sgn); } return ComptimeValue::makeInt(a / b, w, sgn); @@ -364,7 +364,7 @@ ComptimeEvaluator::evalBinaryOp(const AstNode &n, if (sgn) { return ComptimeValue::makeInt( static_cast(static_cast(a) % - static_cast(b)), + static_cast(b)), w, sgn); } return ComptimeValue::makeInt(a % b, w, sgn); @@ -379,7 +379,8 @@ ComptimeEvaluator::evalBinaryOp(const AstNode &n, case BinOp::Shr: if (sgn) { return ComptimeValue::makeInt( - static_cast(static_cast(a) >> b), w, sgn); + static_cast(static_cast(a) >> b), w, + sgn); } return ComptimeValue::makeInt(a >> b, w, sgn); case BinOp::Eq: @@ -387,24 +388,20 @@ ComptimeEvaluator::evalBinaryOp(const AstNode &n, case BinOp::Ne: return ComptimeValue::makeBool(a != b); case BinOp::Lt: - return sgn - ? ComptimeValue::makeBool(static_cast(a) < - static_cast(b)) + return sgn ? ComptimeValue::makeBool(static_cast(a) < + static_cast(b)) : ComptimeValue::makeBool(a < b); case BinOp::Le: - return sgn - ? ComptimeValue::makeBool(static_cast(a) <= - static_cast(b)) + return sgn ? ComptimeValue::makeBool(static_cast(a) <= + static_cast(b)) : ComptimeValue::makeBool(a <= b); case BinOp::Gt: - return sgn - ? ComptimeValue::makeBool(static_cast(a) > - static_cast(b)) + return sgn ? ComptimeValue::makeBool(static_cast(a) > + static_cast(b)) : ComptimeValue::makeBool(a > b); case BinOp::Ge: - return sgn - ? ComptimeValue::makeBool(static_cast(a) >= - static_cast(b)) + return sgn ? ComptimeValue::makeBool(static_cast(a) >= + static_cast(b)) : ComptimeValue::makeBool(a >= b); default: return ComptimeValue::makeNone(); @@ -445,7 +442,7 @@ ComptimeEvaluator::evalBinaryOp(const AstNode &n, ComptimeValue ComptimeEvaluator::evalMemberAccess(const AstNode &n, - const ComptimeScope &scope) const { + const ComptimeScope &scope) const { // Member access on a comp value. v1 supports `.length` on a comp // str (returns u32 byte count). Future: struct field access on a // comp-known aggregate. @@ -457,17 +454,15 @@ ComptimeEvaluator::evalMemberAccess(const AstNode &n, if (base.kind == ComptimeValue::Kind::Str && member == "length") { const std::string &s = strings_.get(base.strVal); return ComptimeValue::makeInt(static_cast(s.length()), 64, - /*isSigned=*/false); + /*isSigned=*/false); } return ComptimeValue::makeNone(); } ExecResult ComptimeEvaluator::execStmt(NodeIdx stmt, ComptimeScope &scope, - uint32_t &iterCounter, - uint32_t iterCap, - ComptimeValue &outReturnValue, - Diagnostics &diags, - SrcLoc loc) const { + uint32_t &iterCounter, uint32_t iterCap, + ComptimeValue &outReturnValue, + Diagnostics &diags, SrcLoc loc) const { if (stmt == kNoNode) return ExecResult::Continue; const AstNode &n = nodes_.get(stmt); @@ -482,9 +477,8 @@ ExecResult ComptimeEvaluator::execStmt(NodeIdx stmt, ComptimeScope &scope, NodeIdx initIdx = static_cast(nodes_.getExtra(extra + 2)); ComptimeValue v = eval(initIdx, scope); if (v.isNone()) { - diags.error(loc, - "comp var-decl initializer must be a " - "compile-time-known value"); + diags.error(loc, "comp var-decl initializer must be a " + "compile-time-known value"); return ExecResult::Error; } scope.bind(strings_.get(nameId), std::move(v)); @@ -496,25 +490,22 @@ ExecResult ComptimeEvaluator::execStmt(NodeIdx stmt, ComptimeScope &scope, NodeIdx valueIdx = static_cast(n.rhs); const AstNode &target = nodes_.get(targetIdx); if (target.tag != AstTag::Variable) { - diags.error(loc, - "comp assignment target must be a bare " - "variable (member-access / index targets are " - "not supported in v1)"); + diags.error(loc, "comp assignment target must be a bare " + "variable (member-access / index targets are " + "not supported in v1)"); return ExecResult::Error; } StringIdx nameId = static_cast(target.lhs); const std::string &name = strings_.get(nameId); ComptimeValue v = eval(valueIdx, scope); if (v.isNone()) { - diags.error(loc, - "comp assignment value must be a compile-" - "time-known value"); + diags.error(loc, "comp assignment value must be a compile-" + "time-known value"); return ExecResult::Error; } if (!scope.set(name, std::move(v))) { - diags.error(loc, - "assignment to undeclared variable `" + name + - "` (declare with `var` first)"); + diags.error(loc, "assignment to undeclared variable `" + name + + "` (declare with `var` first)"); return ExecResult::Error; } return ExecResult::Continue; @@ -540,9 +531,8 @@ ExecResult ComptimeEvaluator::execStmt(NodeIdx stmt, ComptimeScope &scope, stmts.push_back( static_cast(nodes_.getExtra(extra + 2 + i))); } - return execBlock(stmts.data(), stmts.size(), inner, - iterCounter, iterCap, outReturnValue, diags, - loc); + return execBlock(stmts.data(), stmts.size(), inner, iterCounter, + iterCap, outReturnValue, diags, loc); } std::vector stmts; stmts.reserve(elseCount); @@ -567,22 +557,20 @@ ExecResult ComptimeEvaluator::execStmt(NodeIdx stmt, ComptimeScope &scope, while (true) { ComptimeValue c = eval(condIdx, scope); if (c.kind != ComptimeValue::Kind::Bool) { - diags.error(loc, - "comp `while` condition must fold to bool"); + diags.error(loc, "comp `while` condition must fold to bool"); return ExecResult::Error; } if (!c.boolVal) break; if (++iterCounter > iterCap) { - diags.error(loc, - "comp evaluation iteration cap (" + - std::to_string(iterCap) + - ") exceeded — possible infinite loop"); + diags.error(loc, "comp evaluation iteration cap (" + + std::to_string(iterCap) + + ") exceeded — possible infinite loop"); return ExecResult::IterationCap; } ComptimeScope iter(&scope); - ExecResult r = execBlock(body.data(), body.size(), iter, - iterCounter, iterCap, outReturnValue, - diags, loc); + ExecResult r = + execBlock(body.data(), body.size(), iter, iterCounter, iterCap, + outReturnValue, diags, loc); if (r != ExecResult::Continue) return r; } return ExecResult::Continue; @@ -595,9 +583,8 @@ ExecResult ComptimeEvaluator::execStmt(NodeIdx stmt, ComptimeScope &scope, } else { outReturnValue = eval(valIdx, scope); if (outReturnValue.isNone()) { - diags.error(loc, - "comp `return` expression must fold to a " - "value"); + diags.error(loc, "comp `return` expression must fold to a " + "value"); return ExecResult::Error; } } @@ -614,26 +601,21 @@ ExecResult ComptimeEvaluator::execStmt(NodeIdx stmt, ComptimeScope &scope, } } -ExecResult ComptimeEvaluator::execBlock(const NodeIdx *stmts, - std::size_t count, - ComptimeScope &scope, - uint32_t &iterCounter, - uint32_t iterCap, - ComptimeValue &outReturnValue, - Diagnostics &diags, - SrcLoc loc) const { +ExecResult ComptimeEvaluator::execBlock(const NodeIdx *stmts, std::size_t count, + ComptimeScope &scope, + uint32_t &iterCounter, uint32_t iterCap, + ComptimeValue &outReturnValue, + Diagnostics &diags, SrcLoc loc) const { for (std::size_t i = 0; i < count; i++) { - ExecResult r = - execStmt(stmts[i], scope, iterCounter, iterCap, outReturnValue, - diags, loc); + ExecResult r = execStmt(stmts[i], scope, iterCounter, iterCap, + outReturnValue, diags, loc); if (r != ExecResult::Continue) return r; } return ExecResult::Continue; } -ComptimeValue -ComptimeEvaluator::evalIndex(const AstNode &n, - const ComptimeScope &scope) const { +ComptimeValue ComptimeEvaluator::evalIndex(const AstNode &n, + const ComptimeScope &scope) const { NodeIdx baseIdx = static_cast(n.lhs); NodeIdx idxIdx = static_cast(n.rhs); ComptimeValue base = eval(baseIdx, scope); @@ -647,9 +629,9 @@ ComptimeEvaluator::evalIndex(const AstNode &n, const std::string &s = strings_.get(base.strVal); if (i >= s.length()) return ComptimeValue::makeNone(); // Result is the byte value as a u8. - return ComptimeValue::makeInt(static_cast( - static_cast(s[i])), - 8, /*isSigned=*/false); + return ComptimeValue::makeInt( + static_cast(static_cast(s[i])), 8, + /*isSigned=*/false); } if (base.kind == ComptimeValue::Kind::Aggregate) { if (i >= base.aggFields.size()) return ComptimeValue::makeNone(); diff --git a/src/comptime.h b/src/comptime.h index eecbc30..feeff91 100644 --- a/src/comptime.h +++ b/src/comptime.h @@ -147,8 +147,8 @@ class CompEmitter { public: virtual ~CompEmitter() = default; virtual ExecResult handleAtCall(const std::string &name, - const std::vector &args, - Diagnostics &diags, SrcLoc loc) = 0; + const std::vector &args, + Diagnostics &diags, SrcLoc loc) = 0; }; // Folds AST expression nodes to compile-time values. Failure modes @@ -164,7 +164,7 @@ class CompEmitter { class ComptimeEvaluator { public: ComptimeEvaluator(const NodeStore &nodes, const StringPool &strings, - const TypePool &types); + const TypePool &types); // Try to fold `expr` to a value. Returns None on any failure. ComptimeValue eval(NodeIdx expr, const ComptimeScope &scope) const; @@ -174,7 +174,7 @@ class ComptimeEvaluator { // explicitly marked as requiring fold) and by control-flow primitives // where a non-fold is a hard error. ComptimeValue evalRequired(NodeIdx expr, const ComptimeScope &scope, - Diagnostics &diags, SrcLoc loc) const; + Diagnostics &diags, SrcLoc loc) const; // Execute a statement node. The scope is mutated for var-decls and // assignments; control-flow statements (if/while) recurse. The @@ -189,17 +189,17 @@ class ComptimeEvaluator { // fires; otherwise it's left None. static constexpr uint32_t kDefaultIterCap = 10'000; ExecResult execStmt(NodeIdx stmt, ComptimeScope &scope, - uint32_t &iterCounter, uint32_t iterCap, - ComptimeValue &outReturnValue, Diagnostics &diags, - SrcLoc loc) const; + uint32_t &iterCounter, uint32_t iterCap, + ComptimeValue &outReturnValue, Diagnostics &diags, + SrcLoc loc) const; // Execute a sequence of statements in order. Returns the first // non-Continue result. Wraps a list of NodeIdx from an Extra slice // like a fn body or if/while body. ExecResult execBlock(const NodeIdx *stmts, std::size_t count, - ComptimeScope &scope, uint32_t &iterCounter, - uint32_t iterCap, ComptimeValue &outReturnValue, - Diagnostics &diags, SrcLoc loc) const; + ComptimeScope &scope, uint32_t &iterCounter, + uint32_t iterCap, ComptimeValue &outReturnValue, + Diagnostics &diags, SrcLoc loc) const; // Install / clear the AtCall emitter + the diagnostic context. // Active for the duration of a cfn body's execution; cleared @@ -231,22 +231,21 @@ class ComptimeEvaluator { // is forwarded to the installed emitter; returns None as well // (the @-emit family produces side effects, not values). ComptimeValue evalAtCall(const AstNode &n, - const ComptimeScope &scope) const; + const ComptimeScope &scope) const; // Per-tag handlers. Each returns None on failure; callers compose. ComptimeValue evalNumberLit(const AstNode &n) const; ComptimeValue evalBoolLit(const AstNode &n) const; ComptimeValue evalStringLit(const AstNode &n) const; ComptimeValue evalVariable(const AstNode &n, - const ComptimeScope &scope) const; - ComptimeValue evalUnaryOp(const AstNode &n, const ComptimeScope &scope) const; + ComptimeValue evalUnaryOp(const AstNode &n, + const ComptimeScope &scope) const; ComptimeValue evalBinaryOp(const AstNode &n, - const ComptimeScope &scope) const; - ComptimeValue evalIndex(const AstNode &n, - const ComptimeScope &scope) const; + const ComptimeScope &scope) const; + ComptimeValue evalIndex(const AstNode &n, const ComptimeScope &scope) const; ComptimeValue evalMemberAccess(const AstNode &n, - const ComptimeScope &scope) const; + const ComptimeScope &scope) const; }; } // namespace jam diff --git a/src/main.cpp b/src/main.cpp index 314dc92..124bfc7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -127,8 +127,7 @@ static int compileAndRun(const std::string &filename, // `pub const X = import(...)` alias in the preceding module; we // recurse so a re-export that itself walks a chain composes. auto resolveImportChain = - [&](const std::string &basePath, - const std::vector &chain, + [&](const std::string &basePath, const std::vector &chain, auto &self) -> std::pair { std::string curPath = basePath; ModuleAST *curMod = resolver.getOrLoadModule(curPath); @@ -376,46 +375,45 @@ static int compileAndRun(const std::string &filename, // Register every flat `handle.X` mapping for a given (handle name, // resolved module). Shared by direct-import bindings and module- // valued destructuring bindings (`const {fmt} = import("std");`). - auto registerHandleFlats = - [&](const std::string &handle, const std::string &modulePath, - ModuleAST *importedModule) { - codegenCtx.registerImportHandle(handle, modulePath); - auto aliasNamed = [&](const std::string &bare) { - TypeIdx target = codegenCtx.getTypePool().internNamed( - codegenCtx.getStringPool().intern(bare)); - codegenCtx.registerTypeAlias(handle + "." + bare, target); - }; - for (auto &func : importedModule->Functions) { - if (func->isPub) { - codegenCtx.registerFunctionAST(handle + "." + func->Name, - func.get()); - } else { - codegenCtx.registerPrivateName(handle, func->Name); - } - } - for (auto &s : importedModule->Structs) { - if (s->isPub) { - aliasNamed(s->Name); - for (auto &m : s->Methods) { - if (m->isPub) { - codegenCtx.registerFunctionAST( - handle + "." + s->Name + "." + m->Name, - m.get()); - } - } - } else { - codegenCtx.registerPrivateName(handle, s->Name); - } - } - for (auto &e : importedModule->Enums) { - if (e->isPub) aliasNamed(e->Name); - else codegenCtx.registerPrivateName(handle, e->Name); - } - for (auto &u : importedModule->Unions) { - if (u->isPub) aliasNamed(u->Name); - else codegenCtx.registerPrivateName(handle, u->Name); - } - }; + auto registerHandleFlats = [&](const std::string &handle, + const std::string &modulePath, + ModuleAST *importedModule) { + codegenCtx.registerImportHandle(handle, modulePath); + auto aliasNamed = [&](const std::string &bare) { + TypeIdx target = codegenCtx.getTypePool().internNamed( + codegenCtx.getStringPool().intern(bare)); + codegenCtx.registerTypeAlias(handle + "." + bare, target); + }; + for (auto &func : importedModule->Functions) { + if (func->isPub) { + codegenCtx.registerFunctionAST(handle + "." + func->Name, + func.get()); + } else { + codegenCtx.registerPrivateName(handle, func->Name); + } + } + for (auto &s : importedModule->Structs) { + if (s->isPub) { + aliasNamed(s->Name); + for (auto &m : s->Methods) { + if (m->isPub) { + codegenCtx.registerFunctionAST( + handle + "." + s->Name + "." + m->Name, m.get()); + } + } + } else { + codegenCtx.registerPrivateName(handle, s->Name); + } + } + for (auto &e : importedModule->Enums) { + if (e->isPub) aliasNamed(e->Name); + else codegenCtx.registerPrivateName(handle, e->Name); + } + for (auto &u : importedModule->Unions) { + if (u->isPub) aliasNamed(u->Name); + else codegenCtx.registerPrivateName(handle, u->Name); + } + }; for (auto &import : module->Imports) { if (import->Path == "test") continue; diff --git a/src/mangling.h b/src/mangling.h index ca6c5b2..6e6bb3b 100644 --- a/src/mangling.h +++ b/src/mangling.h @@ -46,8 +46,7 @@ inline std::string mangledFunctionName(const FunctionAST &fn, // mut A)` and `cfn drop(self: mut B)` get distinct symbols. Only // kicks in when parentStruct is empty — in-struct `cfn drop` goes // through the standard FQN path below. - if (fn.parentStruct.empty() && fn.Name == "drop" && - fn.Args.size() == 1) { + if (fn.parentStruct.empty() && fn.Name == "drop" && fn.Args.size() == 1) { const Param &p = fn.Args[0]; if (p.Name == "self" && p.Mode == ParamMode::Mut) { const TypeKey &k = types.get(p.Type); diff --git a/src/parser.cpp b/src/parser.cpp index 3484583..02dfd2b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -998,8 +998,8 @@ NodeIdx Parser::parseExpression() { for (size_t i = 0; i < elseBody.size(); i++) { nodes->setExtra(extra + 2 + thenBody.size() + i, elseBody[i]); } - AstNode ifNode{AstTag::IfNode, 0, 0, 0, - static_cast(cond), extra}; + AstNode ifNode{AstTag::IfNode, 0, 0, 0, static_cast(cond), + extra}; ifNode.flags = 1; // bit 0 = comp return emit(ifNode); } @@ -1015,10 +1015,8 @@ NodeIdx Parser::parseExpression() { consume(TOK_WHILE, "Expected `while` after `inline`"); consume(TOK_OPEN_PAREN, "Expected '(' after `inline while`"); NodeIdx cond = parseLogicalOr(); - consume(TOK_CLOSE_PAREN, - "Expected ')' after `inline while` condition"); - consume(TOK_OPEN_BRACE, - "Expected '{' after `inline while` condition"); + consume(TOK_CLOSE_PAREN, "Expected ')' after `inline while` condition"); + consume(TOK_OPEN_BRACE, "Expected '{' after `inline while` condition"); std::vector body; while (!check(TOK_CLOSE_BRACE) && !isAtEnd()) { body.push_back(parseExpression()); @@ -1029,7 +1027,7 @@ NodeIdx Parser::parseExpression() { for (size_t i = 0; i < body.size(); i++) { nodes->setExtra(extra + 1 + i, body[i]); } - AstNode whileNode{AstTag::WhileNode, 0, 0, 0, + AstNode whileNode{AstTag::WhileNode, 0, 0, 0, static_cast(cond), extra}; whileNode.flags = 1; // bit 0 = inline return emit(whileNode); @@ -1476,9 +1474,7 @@ std::unique_ptr Parser::parseFunction() { // function's substitution map at monomorphisation time. // Same per-call instantiation cache as `T: type` generics. bool isComp = false; - if (match(TOK_COMP)) { - isComp = true; - } + if (match(TOK_COMP)) { isComp = true; } consume(TOK_IDENTIFIER, "Expected parameter name"); std::string paramName(previous().text(source_)); @@ -1499,7 +1495,8 @@ std::unique_ptr Parser::parseFunction() { } TypeIdx paramType = parseType(); - args.push_back(Param{std::move(paramName), paramType, mode, isComp}); + args.push_back( + Param{std::move(paramName), paramType, mode, isComp}); } while (match(TOK_COMMA)); } @@ -1759,7 +1756,8 @@ std::unique_ptr Parser::parseImportDecl() { // `import(...)` alias in the preceding module; the final segment's // resolved path is what `name` will bind to. while (match(TOK_DOT)) { - consume(TOK_IDENTIFIER, "Expected identifier after `.` in import chain"); + consume(TOK_IDENTIFIER, + "Expected identifier after `.` in import chain"); decl->chain.emplace_back(previous().text(source_)); } consume(TOK_SEMI, "Expected ';' after import declaration"); @@ -1787,9 +1785,10 @@ std::unique_ptr Parser::parseDestructuringImport() { consume(TOK_CLOSE_PAREN, "Expected ')' after import path"); auto decl = std::make_unique(std::move(names), - std::move(path)); + std::move(path)); while (match(TOK_DOT)) { - consume(TOK_IDENTIFIER, "Expected identifier after `.` in import chain"); + consume(TOK_IDENTIFIER, + "Expected identifier after `.` in import chain"); decl->chain.emplace_back(previous().text(source_)); } consume(TOK_SEMI, "Expected ';' after import declaration"); diff --git a/tests/cpp/test_comptime.cpp b/tests/cpp/test_comptime.cpp index 123d305..db653d8 100644 --- a/tests/cpp/test_comptime.cpp +++ b/tests/cpp/test_comptime.cpp @@ -164,11 +164,11 @@ void testIntAddSubMul() { NodeIdx a = mkInt(ns, 10); NodeIdx b = mkInt(ns, 3); ASSERT_EQ(static_cast(13), - e.eval(mkBinOp(ns, BinOp::Add, a, b), scope).asU64()); + e.eval(mkBinOp(ns, BinOp::Add, a, b), scope).asU64()); ASSERT_EQ(static_cast(7), - e.eval(mkBinOp(ns, BinOp::Sub, a, b), scope).asU64()); + e.eval(mkBinOp(ns, BinOp::Sub, a, b), scope).asU64()); ASSERT_EQ(static_cast(30), - e.eval(mkBinOp(ns, BinOp::Mul, a, b), scope).asU64()); + e.eval(mkBinOp(ns, BinOp::Mul, a, b), scope).asU64()); } void testIntDivByZeroIsNone() { @@ -208,11 +208,11 @@ void testBitwise() { NodeIdx a = mkInt(ns, 0b1100); NodeIdx b = mkInt(ns, 0b1010); ASSERT_EQ(static_cast(0b1000), - e.eval(mkBinOp(ns, BinOp::BitAnd, a, b), scope).asU64()); + e.eval(mkBinOp(ns, BinOp::BitAnd, a, b), scope).asU64()); ASSERT_EQ(static_cast(0b1110), - e.eval(mkBinOp(ns, BinOp::BitOr, a, b), scope).asU64()); + e.eval(mkBinOp(ns, BinOp::BitOr, a, b), scope).asU64()); ASSERT_EQ(static_cast(0b0110), - e.eval(mkBinOp(ns, BinOp::BitXor, a, b), scope).asU64()); + e.eval(mkBinOp(ns, BinOp::BitXor, a, b), scope).asU64()); } // ── Logical operators (short-circuit) ──────────────────────────── @@ -226,7 +226,8 @@ void testLogAndShortCircuits() { NodeIdx f = mkBool(ns, false); // RHS references missing variable — would return None if eval'd. NodeIdx missing = mkVar(ns, sp, "z"); - jam::ComptimeValue v = e.eval(mkBinOp(ns, BinOp::LogAnd, f, missing), scope); + jam::ComptimeValue v = + e.eval(mkBinOp(ns, BinOp::LogAnd, f, missing), scope); ASSERT_TRUE(v.isBool()); ASSERT_FALSE(v.boolVal); // LHS=false short-circuits, never touched RHS } @@ -325,7 +326,8 @@ void testAggregateIndexing() { fields.push_back(jam::ComptimeValue::makeInt(10, 32, true)); fields.push_back(jam::ComptimeValue::makeInt(20, 32, true)); fields.push_back(jam::ComptimeValue::makeInt(30, 32, true)); - jam::ComptimeValue agg = jam::ComptimeValue::makeAggregate(std::move(fields)); + jam::ComptimeValue agg = + jam::ComptimeValue::makeAggregate(std::move(fields)); NodeStore ns; StringPool sp; @@ -401,7 +403,7 @@ void testScopeSetWalksUpToParent() { // ── Helper builders for statement nodes ────────────────────────── NodeIdx mkVarDecl(NodeStore &ns, StringPool &sp, const std::string &name, - NodeIdx init) { + NodeIdx init) { ExtraIdx extra = ns.reserveExtra(3); ns.setExtra(extra, sp.intern(name)); ns.setExtra(extra + 1, kNoType); // type — ignored by comp evaluator @@ -422,8 +424,8 @@ NodeIdx mkAssign(NodeStore &ns, NodeIdx target, NodeIdx value) { } NodeIdx mkIfNode(NodeStore &ns, NodeIdx cond, - const std::vector &thenStmts, - const std::vector &elseStmts) { + const std::vector &thenStmts, + const std::vector &elseStmts) { std::size_t total = 2 + thenStmts.size() + elseStmts.size(); ExtraIdx extra = ns.reserveExtra(total); ns.setExtra(extra, static_cast(thenStmts.size())); @@ -442,7 +444,7 @@ NodeIdx mkIfNode(NodeStore &ns, NodeIdx cond, } NodeIdx mkWhileNode(NodeStore &ns, NodeIdx cond, - const std::vector &body) { + const std::vector &body) { ExtraIdx extra = ns.reserveExtra(1 + body.size()); ns.setExtra(extra, static_cast(body.size())); for (std::size_t i = 0; i < body.size(); i++) { @@ -456,7 +458,7 @@ NodeIdx mkWhileNode(NodeStore &ns, NodeIdx cond, } NodeIdx mkMemberAccess(NodeStore &ns, StringPool &sp, NodeIdx base, - const std::string &member) { + const std::string &member) { AstNode node{}; node.tag = AstTag::MemberAccess; node.lhs = base; @@ -539,8 +541,7 @@ void testExecIfPicksTrueBranch() { // if (true) { x = 1; } else { x = 2; } NodeIdx thenAsn = mkAssign(ns, mkVar(ns, sp, "x"), mkInt(ns, 1)); NodeIdx elseAsn = mkAssign(ns, mkVar(ns, sp, "x"), mkInt(ns, 2)); - NodeIdx ifNode = - mkIfNode(ns, mkBool(ns, true), {thenAsn}, {elseAsn}); + NodeIdx ifNode = mkIfNode(ns, mkBool(ns, true), {thenAsn}, {elseAsn}); jam::ExecResult r = e.execStmt(ifNode, scope, iter, 1000, ret, diags, loc); ASSERT_TRUE(r == jam::ExecResult::Continue); ASSERT_EQ(static_cast(1), scope.lookup("x")->asU64()); @@ -560,8 +561,7 @@ void testExecIfPicksFalseBranch() { scope.bind("x", jam::ComptimeValue::makeInt(0, 64, false)); NodeIdx thenAsn = mkAssign(ns, mkVar(ns, sp, "x"), mkInt(ns, 1)); NodeIdx elseAsn = mkAssign(ns, mkVar(ns, sp, "x"), mkInt(ns, 2)); - NodeIdx ifNode = - mkIfNode(ns, mkBool(ns, false), {thenAsn}, {elseAsn}); + NodeIdx ifNode = mkIfNode(ns, mkBool(ns, false), {thenAsn}, {elseAsn}); e.execStmt(ifNode, scope, iter, 1000, ret, diags, loc); ASSERT_EQ(static_cast(2), scope.lookup("x")->asU64()); } @@ -632,8 +632,8 @@ void testExecBlockShortCircuitsOnError() { NodeIdx bad = mkAssign(ns, mkVar(ns, sp, "y"), mkInt(ns, 1)); NodeIdx good = mkAssign(ns, mkVar(ns, sp, "x"), mkInt(ns, 99)); std::vector body = {d, bad, good}; - jam::ExecResult r = e.execBlock(body.data(), body.size(), scope, iter, - 1000, ret, diags, loc); + jam::ExecResult r = e.execBlock(body.data(), body.size(), scope, iter, 1000, + ret, diags, loc); ASSERT_TRUE(r == jam::ExecResult::Error); // x stays at 0 (the good assign never ran). ASSERT_EQ(static_cast(0), scope.lookup("x")->asU64()); @@ -657,7 +657,8 @@ void testMemberAccessStrLength() { int main() { TestFramework framework; - framework.addTest("Comptime - NumberLit folds to Int", testNumberLitFoldsToInt); + framework.addTest("Comptime - NumberLit folds to Int", + testNumberLitFoldsToInt); framework.addTest("Comptime - BoolLit folds", testBoolLitFolds); framework.addTest("Comptime - StringLit folds", testStringLitFolds); framework.addTest("Comptime - Variable lookup from scope", @@ -682,11 +683,9 @@ int main() { framework.addTest("Comptime - string index out-of-bounds None", testStringIndexOutOfBoundsIsNone); framework.addTest("Comptime - type equality", testTypeEquality); - framework.addTest("Comptime - aggregate indexing", - testAggregateIndexing); - framework.addTest( - "Comptime - evalRequired pushes diagnostic on fail", - testEvalRequiredPushesDiagnosticOnFail); + framework.addTest("Comptime - aggregate indexing", testAggregateIndexing); + framework.addTest("Comptime - evalRequired pushes diagnostic on fail", + testEvalRequiredPushesDiagnosticOnFail); framework.addTest("Comptime - scope set mutates existing", testScopeSetMutatesExistingBinding); framework.addTest("Comptime - scope set returns false for unknown", diff --git a/tests/cpp/test_print.cpp b/tests/cpp/test_print.cpp index 0d96a9d..f9e9f12 100644 --- a/tests/cpp/test_print.cpp +++ b/tests/cpp/test_print.cpp @@ -57,7 +57,7 @@ RunResult compileAndRun(const std::string &name, const std::string &source) { } std::string compileCmd = "./output/jam.out -o " + binPath + " " + srcPath + - " >" + compileLog + " 2>&1"; + " >" + compileLog + " 2>&1"; int compileStatus = std::system(compileCmd.c_str()); int compileExit = WIFEXITED(compileStatus) ? WEXITSTATUS(compileStatus) : -1; @@ -66,8 +66,7 @@ RunResult compileAndRun(const std::string &name, const std::string &source) { return {compileExit, -1, std::move(compileOut), "", ""}; } - std::string runCmd = - binPath + " >" + stdoutFile + " 2>" + stderrFile; + std::string runCmd = binPath + " >" + stdoutFile + " 2>" + stderrFile; int runStatus = std::system(runCmd.c_str()); int runExit = WIFEXITED(runStatus) ? WEXITSTATUS(runStatus) : -1; std::string stdoutContent = readFile(stdoutFile); @@ -289,8 +288,7 @@ fn main() i32 { } )"); ASSERT_EQ(0, r.runExit); - ASSERT_EQ(std::string( - "hello, world! the answer is 42, have a nice day\n"), + ASSERT_EQ(std::string("hello, world! the answer is 42, have a nice day\n"), r.stdout_); } -- 2.51.2