diff --git a/build.zig b/build.zig index 10a1fb4cd..1cdb61ee2 100644 --- a/build.zig +++ b/build.zig @@ -1,31 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -// ── Modular build system ──────────────────────────────────────────────── -const options_mod = @import("build/options.zig"); -const modules = @import("build/modules.zig"); -const flags = @import("build/flags.zig"); -const targets = @import("build/targets.zig"); -const mobile = @import("build/mobile.zig"); -const wasm = @import("build/wasm.zig"); -const gpu = @import("build/gpu.zig"); -const link = @import("build/link.zig"); -const cli_tests = @import("build/cli_tests.zig"); -const test_discovery = @import("build/test_discovery.zig"); - -// Re-export for external use -pub const GpuBackend = gpu.GpuBackend; -pub const BuildOptions = options_mod.BuildOptions; - -comptime { - if (builtin.zig_version.major == 0 and builtin.zig_version.minor < 16) - @compileError(std.fmt.comptimePrint( - "ABI requires Zig 0.16.0 or newer (detected {d}.{d}.{d}). " ++ - "Use `zvm use master` then align to `.zigversion`.", - .{ builtin.zig_version.major, builtin.zig_version.minor, builtin.zig_version.patch }, - )); -} - pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); @@ -64,12 +39,9 @@ pub fn build(b: *std.Build) void { // ── CLI executable ────────────────────────────────────────────────── const exe = b.addExecutable(.{ .name = "abi", - .root_module = b.createModule(.{ - .root_source_file = b.path("tools/cli/main.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }), + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = platform_optimize, }); exe.root_module.addImport("abi", abi_module); exe.root_module.addImport("cli", modules.createCliModule(b, abi_module, target, optimize)); @@ -77,22 +49,52 @@ pub fn build(b: *std.Build) void { link.applyAllPlatformLinks(exe.root_module, target.result.os.tag, options.gpu_metal(), options.gpu_backends); b.installArtifact(exe); - const run_cli = b.addRunArtifact(exe); - if (b.args) |args| run_cli.addArgs(args); - b.step("run", "Run the ABI CLI").dependOn(&run_cli.step); + // ─── Optimization flags ────────────────────────────────────────────────── + exe.link_function_sections = true; + exe.link_gc_sections = true; + if (platform_optimize == .ReleaseSmall or platform_optimize == .ReleaseFast) { + exe.root_module.strip = true; + } - const run_editor = b.addRunArtifact(exe); - run_editor.addArg("ui"); - run_editor.addArg("editor"); - if (b.args) |args| run_editor.addArgs(args); - b.step("editor", "Run the inline CLI TUI editor").dependOn(&run_editor.step); + // No external dependencies currently required. + exe.root_module.addOptions("build_options", options); + + // ─── Platform-specific dependencies ────────────────────────────────────── + switch (target.result.os.tag) { + .linux => { + exe.linkSystemLibrary("c"); + if (b.option(bool, "enable_io_uring", "Enable io_uring support") orelse true) { + exe.linkSystemLibrary("uring"); + } + }, + .windows => { + exe.linkSystemLibrary("kernel32"); + exe.linkSystemLibrary("user32"); + exe.linkSystemLibrary("d3d12"); + }, + .macos, .ios => { + exe.linkFramework("Metal"); + exe.linkFramework("MetalKit"); + exe.linkFramework("CoreGraphics"); + }, + else => {}, + } // ── Examples (table-driven) ───────────────────────────────────────── const examples_step = b.step("examples", "Build all examples"); targets.buildTargets(b, &targets.example_targets, abi_module, build_opts, target, optimize, examples_step, false); - // ── CLI smoke tests ───────────────────────────────────────────────── - const cli_tests_step = cli_tests.addCliTests(b, exe); + const run_cmd = b.addRunArtifact(exe); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the application"); + run_step.dependOn(&run_cmd.step); + + const bench_step = b.step("bench", "Run performance benchmarks"); + const bench_exe = b.addRunArtifact(exe); + bench_exe.addArg("bench"); + bench_exe.addArg("--iterations=1000"); + bench_step.dependOn(&bench_exe.step); // ── TUI / CLI unit tests ─────────────────────────────────────────── var tui_tests_step: ?*std.Build.Step = null; @@ -160,328 +162,10 @@ pub fn build(b: *std.Build) void { // ── Feature tests (manifest-driven) ───────────────────────────────── const feature_tests_step = test_discovery.addFeatureTests(b, options, build_opts, target, optimize); - // ── Flag validation matrix ────────────────────────────────────────── - const validate_flags_step = flags.addFlagValidation(b, target, optimize); - - // ── Import rule check ─────────────────────────────────────────────── - const import_check_step = b.step("check-imports", "Verify no @import(\"abi\") in feature modules"); - import_check_step.dependOn(&addScriptRunner(b, "abi-check-import-rules", "tools/scripts/check_import_rules.zig", target, optimize).step); - - // ── Consistency checks ────────────────────────────────────────────── - const toolchain_doctor_step = b.step("toolchain-doctor", "Diagnose local Zig PATH/version drift against repository pin"); - toolchain_doctor_step.dependOn(&addScriptRunner(b, "abi-toolchain-doctor", "tools/scripts/toolchain_doctor.zig", target, optimize).step); - - const consistency_step = b.step("check-consistency", "Verify Zig version/baseline consistency and Zig 0.16 conformance patterns"); - consistency_step.dependOn(&addScriptRunner(b, "abi-check-zig-version-consistency", "tools/scripts/check_zig_version_consistency.zig", target, optimize).step); - consistency_step.dependOn(&addScriptRunner(b, "abi-check-test-baseline-consistency", "tools/scripts/check_test_baseline_consistency.zig", target, optimize).step); - consistency_step.dependOn(&addScriptRunner(b, "abi-check-zig-016-patterns", "tools/scripts/check_zig_016_patterns.zig", target, optimize).step); - consistency_step.dependOn(&addScriptRunner(b, "abi-check-feature-catalog", "tools/scripts/check_feature_catalog.zig", target, optimize).step); - - if (targets.pathExists(b, "tools/scripts/check_gpu_policy_consistency.zig")) { - const gpu_policy_check_module = b.createModule(.{ - .root_source_file = b.path("tools/scripts/check_gpu_policy_consistency.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - gpu_policy_check_module.addImport("build_gpu_policy", b.createModule(.{ - .root_source_file = b.path("build/gpu_policy.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - })); - gpu_policy_check_module.addImport("runtime_gpu_policy", b.createModule(.{ - .root_source_file = b.path("src/features/gpu/policy/mod.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - })); - const check_gpu_policy_exe = b.addExecutable(.{ - .name = "abi-check-gpu-policy-consistency", - .root_module = gpu_policy_check_module, - }); - consistency_step.dependOn(&b.addRunArtifact(check_gpu_policy_exe).step); - } - - const ralph_gate_step = b.step("ralph-gate", "Require live Ralph scoring report and threshold pass"); - ralph_gate_step.dependOn(&addScriptRunner(b, "abi-check-ralph-gate", "tools/scripts/check_ralph_gate.zig", target, optimize).step); - - const workflow_contract_step = b.step("check-workflow-orchestration", "Advisory workflow-orchestration contract checks"); - workflow_contract_step.dependOn(&addScriptRunner( - b, - "abi-check-workflow-orchestration", - "tools/scripts/check_workflow_orchestration.zig", - target, - optimize, - ).step); - - const workflow_contract_strict_step = b.step("check-workflow-orchestration-strict", "Strict workflow-orchestration contract checks"); - const workflow_contract_strict = addScriptRunner( - b, - "abi-check-workflow-orchestration-strict", - "tools/scripts/check_workflow_orchestration.zig", - target, - optimize, - ); - workflow_contract_strict.addArg("--strict"); - workflow_contract_strict_step.dependOn(&workflow_contract_strict.step); - - // ── CLI DSL registry/codegen ─────────────────────────────────────── - const generate_cli_registry = addScriptRunner( - b, - "abi-generate-cli-registry", - "tools/scripts/generate_cli_registry.zig", - target, - optimize, - ); - generate_cli_registry.addArg("--output"); - generate_cli_registry.addArg(".zig-cache/abi/generated/cli_registry.zig"); - const generate_cli_registry_step = b.step("generate-cli-registry", "Generate CLI registry artifact in build cache"); - generate_cli_registry_step.dependOn(&generate_cli_registry.step); - - const refresh_cli_registry = addScriptRunner( - b, - "abi-refresh-cli-registry", - "tools/scripts/generate_cli_registry.zig", - target, - optimize, - ); - refresh_cli_registry.addArg("--snapshot"); - const refresh_cli_registry_step = b.step("refresh-cli-registry", "Refresh tracked CLI registry snapshot"); - refresh_cli_registry_step.dependOn(&refresh_cli_registry.step); - - const check_cli_registry = addScriptRunner( - b, - "abi-check-cli-registry", - "tools/scripts/generate_cli_registry.zig", - target, - optimize, - ); - check_cli_registry.addArg("--check"); - check_cli_registry.addArg("--snapshot"); - const check_cli_registry_step = b.step("check-cli-registry", "Check CLI registry snapshot determinism"); - check_cli_registry_step.dependOn(&check_cli_registry.step); - - const check_cli_dsl_consistency_step = b.step("check-cli-dsl-consistency", "Verify CLI/TUI DSL organization contracts"); - check_cli_dsl_consistency_step.dependOn(&addScriptRunner( - b, - "abi-check-cli-dsl-consistency", - "tools/scripts/check_cli_dsl_consistency.zig", - target, - optimize, - ).step); - - // ── Baseline validation ───────────────────────────────────────────── - const validate_baseline_step = b.step("validate-baseline", "Run tests and verify counts match tools/scripts/baseline.zig"); - const validate_baseline = addScriptRunner(b, "abi-validate-test-counts", "tools/scripts/validate_test_counts.zig", target, optimize); - validate_baseline.addArg("--main-only"); - if (test_step) |ts| validate_baseline.step.dependOn(ts); - validate_baseline_step.dependOn(&validate_baseline.step); - - // ── Full check ────────────────────────────────────────────────────── - const full_check_step = b.step("full-check", "Run formatting, unit tests, CLI smoke tests, and flag validation"); - full_check_step.dependOn(&lint_fmt.step); - if (test_step) |ts| full_check_step.dependOn(ts); - full_check_step.dependOn(cli_tests_step); - full_check_step.dependOn(validate_flags_step); - full_check_step.dependOn(import_check_step); - full_check_step.dependOn(consistency_step); - full_check_step.dependOn(check_cli_registry_step); - full_check_step.dependOn(check_cli_dsl_consistency_step); - if (tui_tests_step) |step| full_check_step.dependOn(step); - - var check_docs_step: ?*std.Build.Step = null; - - // ── Documentation ─────────────────────────────────────────────────── - if (targets.pathExists(b, "tools/gendocs/main.zig")) { - const gendocs_module = b.createModule(.{ - .root_source_file = b.path("tools/gendocs/main.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - }); - gendocs_module.addImport("roadmap_catalog", b.createModule(.{ - .root_source_file = b.path("src/services/tasks/roadmap_catalog.zig"), - .target = target, - .optimize = optimize, - .link_libc = true, - })); - - const gendocs = b.addExecutable(.{ - .name = "gendocs", - .root_module = gendocs_module, - }); - const run_gendocs = b.addRunArtifact(gendocs); - if (b.args) |args| run_gendocs.addArgs(args); - b.step("gendocs", "Generate docs/api, docs/_docs, docs/plans, and docs/api-app").dependOn(&run_gendocs.step); - - const run_check_docs = b.addRunArtifact(gendocs); - run_check_docs.addArg("--check"); - run_check_docs.addArg("--untracked-md"); - const docs_check = b.step("check-docs", "Validate docs generator determinism and output policy"); - docs_check.dependOn(&run_check_docs.step); - check_docs_step = docs_check; - } - - // ── Profile build ─────────────────────────────────────────────────── - var profile_opts = options; - profile_opts.enable_profiling = true; - const abi_profile = modules.createAbiModule(b, profile_opts, target, optimize); - const profile_exe = b.addExecutable(.{ - .name = "abi-profile", - .root_module = b.createModule(.{ - .root_source_file = b.path("tools/cli/main.zig"), - .target = target, - .optimize = .ReleaseFast, - .link_libc = true, - }), - }); - const profile_mod = profile_exe.root_module; - profile_mod.addImport("abi", abi_profile); - profile_mod.addImport("cli", modules.createCliModule(b, abi_profile, target, optimize)); - profile_mod.strip = false; - profile_mod.omit_frame_pointer = false; - link.applyAllPlatformLinks(profile_mod, target.result.os.tag, options.gpu_metal(), options.gpu_backends); - b.installArtifact(profile_exe); - b.step("profile", "Build with performance profiling").dependOn(b.getInstallStep()); - - // ── Mobile ────────────────────────────────────────────────────────── - _ = mobile.addMobileBuild(b, options, optimize); - - // ── C Library ──────────────────────────────────────────────────────── - const c_bindings_src = "bindings/c/src/abi_c.zig"; - const c_bindings_header = "bindings/c/include/abi.h"; - if (targets.pathExists(b, c_bindings_src) and targets.pathExists(b, c_bindings_header)) { - const lib = b.addLibrary(.{ - .name = "abi", - .root_module = b.createModule(.{ - .root_source_file = b.path(c_bindings_src), - .target = target, - .optimize = optimize, - .link_libc = true, - }), - .linkage = .dynamic, - }); - lib.root_module.addImport("abi", abi_module); - lib.root_module.addImport("build_options", build_opts); - b.step("lib", "Build C shared library").dependOn(&b.addInstallArtifact(lib, .{}).step); - - const header_install = b.addInstallFile(b.path(c_bindings_header), "include/abi.h"); - b.step("c-header", "Install C header file").dependOn(&header_install.step); - } else { - _ = b.step("lib", "Build C shared library (C bindings unavailable in this checkout)"); - const generated = b.addWriteFiles(); - const placeholder_header = generated.add("abi.h", - \\/* ABI C header placeholder. - \\ * Full C bindings are not present in this checkout. - \\ */ - \\#pragma once - \\ - ); - const header_install = b.addInstallFile(placeholder_header, "include/abi.h"); - b.step("c-header", "Install C header file").dependOn(&header_install.step); - } - - // ── Performance verification tool ─────────────────────────────────── - if (targets.pathExists(b, "tools/perf/check.zig")) { - const check_perf_exe = b.addExecutable(.{ - .name = "abi-check-perf", - .root_module = b.createModule(.{ - .root_source_file = b.path("tools/perf/check.zig"), - .target = target, - .optimize = .ReleaseSafe, - }), - }); - b.step("check-perf", "Build performance verification tool (pipe benchmark JSON to run)") - .dependOn(&b.addInstallArtifact(check_perf_exe, .{}).step); - } - - // ── WASM ──────────────────────────────────────────────────────────── - const check_wasm_step = wasm.addWasmBuild(b, options, abi_module, optimize); - - // ── Cross-compilation platform matrix ──────────────────────────────── - const cross_check_step = b.step( - "cross-check", - "Verify the abi module compiles for all supported platform targets", - ); - const cross_targets = targets.cross_check_targets; - inline for (cross_targets) |ct| { - const cross_target = b.resolveTargetQuery(.{ - .cpu_arch = ct.arch, - .os_tag = ct.os, - .abi = ct.abi, - }); - var cross_opts = options; - // Disable features that cannot compile for non-native targets - cross_opts.enable_mobile = false; - if (ct.os == .wasi or ct.os == .freestanding or ct.os == .emscripten) { - cross_opts.enable_database = false; - cross_opts.enable_network = false; - cross_opts.enable_gpu = false; - cross_opts.enable_profiling = false; - cross_opts.enable_web = false; - cross_opts.enable_cloud = false; - cross_opts.enable_storage = false; - cross_opts.gpu_backends = &.{}; - } else { - cross_opts.gpu_backends = &.{.stdgpu}; - } - const cross_build_opts = modules.createBuildOptionsModule(b, cross_opts); - const cross_abi_mod = b.createModule(.{ - .root_source_file = b.path("src/abi.zig"), - .target = cross_target, - .optimize = optimize, - }); - cross_abi_mod.addImport("build_options", cross_build_opts); - const cross_lib = b.addLibrary(.{ - .name = "cross-" ++ ct.name, - .root_module = cross_abi_mod, - .linkage = .static, - }); - cross_check_step.dependOn(&cross_lib.step); - } - - // ── Verify-all ────────────────────────────────────────────────────── - const gate_hardening_step = b.step("gate-hardening", "Run deterministic gate hardening checks"); - gate_hardening_step.dependOn(toolchain_doctor_step); - if (typecheck_step) |step| gate_hardening_step.dependOn(step); - gate_hardening_step.dependOn(cli_tests_step); - if (tui_tests_step) |step| gate_hardening_step.dependOn(step); - gate_hardening_step.dependOn(check_cli_registry_step); - if (check_docs_step) |step| gate_hardening_step.dependOn(step); - gate_hardening_step.dependOn(workflow_contract_strict_step); - gate_hardening_step.dependOn(full_check_step); - - const verify_all_step = b.step("verify-all", "full-check + consistency + feature-tests + examples + check-wasm + cross-check"); - verify_all_step.dependOn(full_check_step); - verify_all_step.dependOn(consistency_step); - if (feature_tests_step) |fts| verify_all_step.dependOn(fts); - verify_all_step.dependOn(examples_step); - if (check_wasm_step) |s| verify_all_step.dependOn(s); - if (check_docs_step) |docs_step| verify_all_step.dependOn(docs_step); - verify_all_step.dependOn(cross_check_step); -} - -// ── Helpers ───────────────────────────────────────────────────────────── - -/// Build and run a standalone Zig script (used for consistency checks, gate -/// checks, etc.). Returns the `Run` step so callers can add arguments or -/// set dependencies. -fn addScriptRunner( - b: *std.Build, - name: []const u8, - source: []const u8, - target: std.Build.ResolvedTarget, - optimize: std.builtin.OptimizeMode, -) *std.Build.Step.Run { - const exe = b.addExecutable(.{ - .name = name, - .root_module = b.createModule(.{ - .root_source_file = b.path(source), - .target = target, - .optimize = optimize, - .link_libc = true, - }), - }); - return b.addRunArtifact(exe); +fn detectSIMDSupport() bool { + return switch (builtin.cpu.arch) { + .x86_64 => std.Target.x86.featureSetHas(builtin.cpu.features, .avx2), + .aarch64 => std.Target.aarch64.featureSetHas(builtin.cpu.features, .neon), + else => false, + }; } diff --git a/ouro_lang.cc b/ouro_lang.cc new file mode 100644 index 000000000..3da132d92 --- /dev/null +++ b/ouro_lang.cc @@ -0,0 +1,620 @@ +// ouro_lang.cc - OuroLang implementation +// Provided by user; integrated into repository. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Token definitions and structures +enum class TokenType { + LET, FN, IF, ELSE, RETURN, FOR, IN, ASYNC, AWAIT, GPU, + INT, FLOAT, STRING, IDENTIFIER, NUMBER, STRING_LITERAL, + COLON, EQUALS, LPAREN, RPAREN, LBRACE, RBRACE, SEMICOLON, COMMA, + PLUS, MINUS, MUL, DIV, GT, DOTDOT, ARROW, EOF_TOKEN +}; + +struct Token { + TokenType type; + std::string value; + int line; +}; + +class Lexer { + std::string source; + size_t pos = 0; + int line = 1; + +public: + explicit Lexer(const std::string &src) : source(src) {} + + std::vector tokenize() { + std::vector tokens; + while (pos < source.size()) { + char c = source[pos]; + if (std::isspace(static_cast(c))) { + if (c == '\n') line++; + pos++; + continue; + } + if (std::isalpha(static_cast(c)) || c == '_') { + tokens.push_back(parse_identifier()); + } else if (std::isdigit(static_cast(c)) || c == '.') { + tokens.push_back(parse_number()); + } else if (c == '"') { + tokens.push_back(parse_string()); + } else { + tokens.push_back(parse_symbol()); + } + } + tokens.push_back({TokenType::EOF_TOKEN, "", line}); + return tokens; + } + +private: + Token parse_identifier() { + std::string value; + while (pos < source.size() && + (std::isalnum(static_cast(source[pos])) || + source[pos] == '_')) { + value += source[pos++]; + } + if (value == "let") return {TokenType::LET, value, line}; + if (value == "fn") return {TokenType::FN, value, line}; + if (value == "if") return {TokenType::IF, value, line}; + if (value == "else") return {TokenType::ELSE, value, line}; + if (value == "return") return {TokenType::RETURN, value, line}; + if (value == "for") return {TokenType::FOR, value, line}; + if (value == "in") return {TokenType::IN, value, line}; + if (value == "async") return {TokenType::ASYNC, value, line}; + if (value == "await") return {TokenType::AWAIT, value, line}; + if (value == "gpu") return {TokenType::GPU, value, line}; + if (value == "int") return {TokenType::INT, value, line}; + if (value == "float") return {TokenType::FLOAT, value, line}; + if (value == "string") return {TokenType::STRING, value, line}; + return {TokenType::IDENTIFIER, value, line}; + } + + Token parse_number() { + std::string value; + bool has_dot = false; + while (pos < source.size() && (std::isdigit(static_cast(source[pos])) || source[pos] == '.')) { + if (source[pos] == '.') has_dot = true; + value += source[pos++]; + } + return {TokenType::NUMBER, value, line}; + } + + Token parse_string() { + std::string value; + pos++; // Skip opening quote + while (pos < source.size() && source[pos] != '"') { + value += source[pos++]; + } + pos++; // Skip closing quote + return {TokenType::STRING_LITERAL, value, line}; + } + + Token parse_symbol() { + char c = source[pos++]; + switch (c) { + case ':': return {TokenType::COLON, ":", line}; + case '=': return {TokenType::EQUALS, "=", line}; + case '(': return {TokenType::LPAREN, "(", line}; + case ')': return {TokenType::RPAREN, ")", line}; + case '{': return {TokenType::LBRACE, "{", line}; + case '}': return {TokenType::RBRACE, "}", line}; + case ';': return {TokenType::SEMICOLON, ";", line}; + case ',': return {TokenType::COMMA, ",", line}; + case '+': return {TokenType::PLUS, "+", line}; + case '-': + if (pos < source.size() && source[pos] == '>') { + pos++; + return {TokenType::ARROW, "->", line}; + } + return {TokenType::MINUS, "-", line}; + case '*': return {TokenType::MUL, "*", line}; + case '/': return {TokenType::DIV, "/", line}; + case '>': return {TokenType::GT, ">", line}; + case '.': + if (pos < source.size() && source[pos] == '.') { + pos++; + return {TokenType::DOTDOT, "..", line}; + } + default: + throw std::runtime_error("Unknown symbol at line " + std::to_string(line)); + } + } +}; + +// Forward declarations for AST structures +struct Expr; +struct Stmt; +using ExprPtr = std::unique_ptr; +using StmtPtr = std::unique_ptr; + +// Expression node types +struct NumberExpr { double value; }; +struct StringExpr { std::string value; }; +struct IdentExpr { std::string name; }; +struct BinaryExpr { TokenType op; ExprPtr left; ExprPtr right; }; +struct CallExpr { std::string name; std::vector args; }; +struct AwaitExpr { ExprPtr expr; }; + +using ExprVariant = std::variant; +struct Expr { ExprVariant value; }; + +// Statement node types +struct VarDeclStmt { std::string name; std::string type; ExprPtr value; }; +struct FnDeclStmt { + std::string name; + std::vector> params; + std::string return_type; + std::vector body; + bool is_async; + bool is_gpu; + bool is_generic; + std::vector generic_params; +}; +struct IfStmt { ExprPtr condition; std::vector then_branch; std::vector else_branch; }; +struct ForStmt { std::string var; ExprPtr start; ExprPtr end; std::vector body; }; +struct ReturnStmt { ExprPtr value; }; + +using StmtVariant = std::variant; +struct Stmt { StmtVariant value; }; + +class Parser { + std::vector tokens; + size_t pos = 0; + +public: + explicit Parser(const std::vector &t) : tokens(t) {} + + std::vector parse() { + std::vector stmts; + while (tokens[pos].type != TokenType::EOF_TOKEN) { + stmts.push_back(parse_stmt()); + } + return stmts; + } + +private: + Token peek() const { return tokens[pos]; } + Token advance() { return tokens[pos++]; } + Token consume(TokenType type, const std::string &msg) { + if (peek().type == type) return advance(); + throw std::runtime_error(msg + " at line " + std::to_string(peek().line)); + } + + StmtPtr parse_stmt() { + if (peek().type == TokenType::LET) return parse_var_decl(); + if (peek().type == TokenType::FN || peek().type == TokenType::ASYNC || peek().type == TokenType::GPU) { + return parse_fn_decl(); + } + if (peek().type == TokenType::IF) return parse_if_stmt(); + if (peek().type == TokenType::FOR) return parse_for_stmt(); + if (peek().type == TokenType::RETURN) return parse_return_stmt(); + throw std::runtime_error("Unexpected token at line " + std::to_string(peek().line)); + } + + StmtPtr parse_var_decl() { + consume(TokenType::LET, "Expected 'let'"); + auto name = consume(TokenType::IDENTIFIER, "Expected identifier").value; + std::string type; + if (peek().type == TokenType::COLON) { + consume(TokenType::COLON, "Expected ':'"); + type = consume(TokenType::IDENTIFIER, "Expected type").value; + } + consume(TokenType::EQUALS, "Expected '='"); + auto value = parse_expr(); + consume(TokenType::SEMICOLON, "Expected ';'"); + return std::make_unique(VarDeclStmt{name, type, std::move(value)}); + } + + StmtPtr parse_fn_decl() { + bool is_async = false, is_gpu = false, is_generic = false; + std::vector generic_params; + if (peek().type == TokenType::ASYNC) { + consume(TokenType::ASYNC, ""); + is_async = true; + } else if (peek().type == TokenType::GPU) { + consume(TokenType::GPU, ""); + is_gpu = true; + } + consume(TokenType::FN, "Expected 'fn'"); + auto name = consume(TokenType::IDENTIFIER, "Expected identifier").value; + if (peek().type == TokenType::GT) { + consume(TokenType::GT, "Expected '<'"); + while (peek().type != TokenType::GT) { + generic_params.push_back(consume(TokenType::IDENTIFIER, "Expected generic param").value); + if (peek().type == TokenType::COMMA) consume(TokenType::COMMA, ""); + } + consume(TokenType::GT, "Expected '>'"); + is_generic = true; + } + consume(TokenType::LPAREN, "Expected '('"); + std::vector> params; + if (peek().type != TokenType::RPAREN) { + do { + auto param_name = consume(TokenType::IDENTIFIER, "Expected param name").value; + consume(TokenType::COLON, "Expected ':'"); + auto param_type = consume(TokenType::IDENTIFIER, "Expected param type").value; + params.push_back({param_name, param_type}); + if (peek().type == TokenType::COMMA) consume(TokenType::COMMA, ""); + } while (peek().type != TokenType::RPAREN); + } + consume(TokenType::RPAREN, "Expected ')'"); + std::string return_type; + if (peek().type == TokenType::ARROW) { + consume(TokenType::ARROW, "Expected '->'"); + return_type = consume(TokenType::IDENTIFIER, "Expected return type").value; + } + consume(TokenType::LBRACE, "Expected '{'"); + std::vector body; + while (peek().type != TokenType::RBRACE) { + body.push_back(parse_stmt()); + } + consume(TokenType::RBRACE, "Expected '}'"); + return std::make_unique(FnDeclStmt{name, params, return_type, std::move(body), + is_async, is_gpu, is_generic, generic_params}); + } + + StmtPtr parse_if_stmt() { + consume(TokenType::IF, "Expected 'if'"); + auto condition = parse_expr(); + consume(TokenType::LBRACE, "Expected '{'"); + std::vector then_branch; + while (peek().type != TokenType::RBRACE && peek().type != TokenType::ELSE) { + then_branch.push_back(parse_stmt()); + } + consume(TokenType::RBRACE, "Expected '}'"); + std::vector else_branch; + if (peek().type == TokenType::ELSE) { + consume(TokenType::ELSE, ""); + consume(TokenType::LBRACE, "Expected '{'"); + while (peek().type != TokenType::RBRACE) { + else_branch.push_back(parse_stmt()); + } + consume(TokenType::RBRACE, "Expected '}'"); + } + return std::make_unique(IfStmt{std::move(condition), std::move(then_branch), std::move(else_branch)}); + } + + StmtPtr parse_for_stmt() { + consume(TokenType::FOR, "Expected 'for'"); + auto var = consume(TokenType::IDENTIFIER, "Expected loop variable").value; + consume(TokenType::IN, "Expected 'in'"); + auto start = parse_expr(); + consume(TokenType::DOTDOT, "Expected '..'"); + auto end = parse_expr(); + consume(TokenType::LBRACE, "Expected '{'"); + std::vector body; + while (peek().type != TokenType::RBRACE) { + body.push_back(parse_stmt()); + } + consume(TokenType::RBRACE, "Expected '}'"); + return std::make_unique(ForStmt{var, std::move(start), std::move(end), std::move(body)}); + } + + StmtPtr parse_return_stmt() { + consume(TokenType::RETURN, "Expected 'return'"); + ExprPtr value; + if (peek().type != TokenType::SEMICOLON) { + value = parse_expr(); + } + consume(TokenType::SEMICOLON, "Expected ';'"); + return std::make_unique(ReturnStmt{std::move(value)}); + } + + ExprPtr parse_expr() { return parse_binary_expr(0); } + + ExprPtr parse_binary_expr(int precedence) { + auto left = parse_primary_expr(); + while (true) { + TokenType op = peek().type; + int op_precedence = get_precedence(op); + if (op_precedence <= precedence) break; + advance(); + auto right = parse_binary_expr(op_precedence); + left = std::make_unique(BinaryExpr{op, std::move(left), std::move(right)}); + } + return left; + } + + int get_precedence(TokenType op) { + switch (op) { + case TokenType::MUL: + case TokenType::DIV: return 2; + case TokenType::PLUS: + case TokenType::MINUS: return 1; + case TokenType::GT: return 0; + default: return -1; + } + } + + ExprPtr parse_primary_expr() { + if (peek().type == TokenType::NUMBER) { + double val = std::stod(consume(TokenType::NUMBER, "Expected number").value); + return std::make_unique(NumberExpr{val}); + } + if (peek().type == TokenType::STRING_LITERAL) { + auto val = consume(TokenType::STRING_LITERAL, "Expected string").value; + return std::make_unique(StringExpr{val}); + } + if (peek().type == TokenType::IDENTIFIER) { + auto name = consume(TokenType::IDENTIFIER, "Expected identifier").value; + if (peek().type == TokenType::LPAREN) { + consume(TokenType::LPAREN, "Expected '('"); + std::vector args; + if (peek().type != TokenType::RPAREN) { + do { + args.push_back(parse_expr()); + if (peek().type == TokenType::COMMA) consume(TokenType::COMMA, ""); + } while (peek().type != TokenType::RPAREN); + } + consume(TokenType::RPAREN, "Expected ')'"); + return std::make_unique(CallExpr{name, std::move(args)}); + } + return std::make_unique(IdentExpr{name}); + } + if (peek().type == TokenType::AWAIT) { + consume(TokenType::AWAIT, "Expected 'await'"); + auto expr = parse_expr(); + return std::make_unique(AwaitExpr{std::move(expr)}); + } + throw std::runtime_error("Expected expression at line " + std::to_string(peek().line)); + } +}; + +class TypeChecker { + std::map env; + std::map functions; + +public: + void check(const std::vector &stmts) { + for (const auto &stmt : stmts) { + check_stmt(*stmt); + } + } + +private: + void check_stmt(const Stmt &stmt) { + if (auto *var = std::get_if(&stmt.value)) { + auto inferred_type = infer_type(var->value.get()); + if (!var->type.empty() && var->type != inferred_type) { + throw std::runtime_error("Type mismatch for " + var->name); + } + env[var->name] = var->type.empty() ? inferred_type : var->type; + } else if (auto *fn = std::get_if(&stmt.value)) { + functions[fn->name] = fn; + auto saved = env; + for (const auto ¶m : fn->params) { + env[param.first] = param.second; + } + for (const auto &body_stmt : fn->body) { + check_stmt(*body_stmt); + } + env = saved; + } else if (auto *if_stmt = std::get_if(&stmt.value)) { + if (infer_type(if_stmt->condition.get()) != "int") { + throw std::runtime_error("If condition must be int"); + } + for (const auto &s : if_stmt->then_branch) check_stmt(*s); + for (const auto &s : if_stmt->else_branch) check_stmt(*s); + } else if (auto *for_stmt = std::get_if(&stmt.value)) { + if (infer_type(for_stmt->start.get()) != "int" || infer_type(for_stmt->end.get()) != "int") { + throw std::runtime_error("For loop bounds must be int"); + } + env[for_stmt->var] = "int"; + for (const auto &s : for_stmt->body) check_stmt(*s); + } else if (auto *ret = std::get_if(&stmt.value)) { + if (ret->value) { + /* additional checks could go here */ + } + } + } + + std::string infer_type(const Expr *expr) { + if (std::holds_alternative(expr->value)) { + return "float"; + } else if (std::holds_alternative(expr->value)) { + return "string"; + } else if (auto *ident = std::get_if(&expr->value)) { + auto it = env.find(ident->name); + if (it != env.end()) return it->second; + throw std::runtime_error("Undefined variable: " + ident->name); + } else if (auto *bin = std::get_if(&expr->value)) { + auto left_type = infer_type(bin->left.get()); + auto right_type = infer_type(bin->right.get()); + if (left_type != right_type) throw std::runtime_error("Type mismatch in binary op"); + if (bin->op == TokenType::GT) return "int"; + return left_type; + } else if (auto *call = std::get_if(&expr->value)) { + auto it = functions.find(call->name); + if (it != functions.end()) { + return it->second->return_type; + } + throw std::runtime_error("Undefined function: " + call->name); + } + return "unknown"; + } +}; + +class Interpreter { + using Value = std::variant; + using NativeFn = std::function &, Interpreter &)>; + +public: + std::map> env; + Value return_value; + + Interpreter() { + env["print"] = NativeFn{[](const std::vector &args, Interpreter &) -> Value { + for (const auto &arg : args) { + if (std::holds_alternative(arg)) { + std::cout << std::get(arg) << ' '; + } else if (std::holds_alternative(arg)) { + std::cout << std::get(arg) << ' '; + } + } + std::cout << std::endl; + return {}; + }}; + + env["sleep"] = NativeFn{[](const std::vector &args, Interpreter &) -> Value { + if (!args.empty() && std::holds_alternative(args[0])) { + auto ms = static_cast(std::get(args[0])); + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + } + return {}; + }}; + } + + void run(const std::string &source) { + Lexer lexer(source); + auto tokens = lexer.tokenize(); + Parser parser(tokens); + auto ast = parser.parse(); + TypeChecker checker; + checker.check(ast); + for (const auto &stmt : ast) { + execute_stmt(*stmt); + } + } + +private: + void execute_stmt(const Stmt &stmt) { + if (auto *var = std::get_if(&stmt.value)) { + env[var->name] = evaluate_expr(*var->value); + } else if (auto *fn = std::get_if(&stmt.value)) { + auto func = [this, fn](const std::vector &args, Interpreter &interpreter) -> Value { + std::map> fn_env = env; + if (args.size() != fn->params.size()) { + throw std::runtime_error("Argument count mismatch"); + } + for (size_t i = 0; i < args.size(); ++i) { + fn_env[fn->params[i].first] = args[i]; + } + if (fn->is_async) { + auto future = std::async(std::launch::async, [fn, fn_env, &interpreter]() mutable { + Interpreter local_interp; + local_interp.env = fn_env; + for (const auto &body_stmt : fn->body) { + local_interp.execute_stmt(*body_stmt); + } + return local_interp.return_value; + }); + return future.get(); + } else if (fn->is_gpu) { + std::cout << "GPU function " << fn->name << " called (placeholder)\n"; + return {}; + } else { + Interpreter local_interp; + local_interp.env = fn_env; + for (const auto &body_stmt : fn->body) { + local_interp.execute_stmt(*body_stmt); + } + return local_interp.return_value; + } + }; + env[fn->name] = func; + } else if (auto *if_stmt = std::get_if(&stmt.value)) { + auto cond = evaluate_expr(*if_stmt->condition); + bool is_true = false; + if (std::holds_alternative(cond)) { + is_true = std::get(cond) != 0; + } + if (is_true) { + for (const auto &s : if_stmt->then_branch) execute_stmt(*s); + } else { + for (const auto &s : if_stmt->else_branch) execute_stmt(*s); + } + } else if (auto *for_stmt = std::get_if(&stmt.value)) { + auto start_val = evaluate_expr(*for_stmt->start); + auto end_val = evaluate_expr(*for_stmt->end); + if (std::holds_alternative(start_val) && std::holds_alternative(end_val)) { + int s = static_cast(std::get(start_val)); + int e = static_cast(std::get(end_val)); + for (int i = s; i < e; ++i) { + env[for_stmt->var] = static_cast(i); + for (const auto &s : for_stmt->body) { + execute_stmt(*s); + } + } + } + } else if (auto *ret = std::get_if(&stmt.value)) { + if (ret->value) { + return_value = evaluate_expr(*ret->value); + } else { + return_value = {}; + } + } + } + + Value evaluate_expr(const Expr &expr) { + if (auto *num = std::get_if(&expr.value)) { + return num->value; + } else if (auto *str = std::get_if(&expr.value)) { + return str->value; + } else if (auto *ident = std::get_if(&expr.value)) { + auto it = env.find(ident->name); + if (it != env.end()) return std::get(it->second); + throw std::runtime_error("Undefined variable: " + ident->name); + } else if (auto *bin = std::get_if(&expr.value)) { + auto left = evaluate_expr(*bin->left); + auto right = evaluate_expr(*bin->right); + if (std::holds_alternative(left) && std::holds_alternative(right)) { + double l = std::get(left); + double r = std::get(right); + switch (bin->op) { + case TokenType::PLUS: return l + r; + case TokenType::MINUS: return l - r; + case TokenType::MUL: return l * r; + case TokenType::DIV: return l / r; + case TokenType::GT: return static_cast(l > r); + default: throw std::runtime_error("Invalid operator"); + } + } + } else if (auto *call = std::get_if(&expr.value)) { + auto it = env.find(call->name); + if (it == env.end()) throw std::runtime_error("Undefined function: " + call->name); + auto func = std::get(it->second); + std::vector args; + for (const auto &arg : call->args) { + args.push_back(evaluate_expr(*arg)); + } + return func(args, *this); + } else if (auto *await = std::get_if(&expr.value)) { + return evaluate_expr(*await->expr); // sync for now + } + throw std::runtime_error("Invalid expression"); + } +}; + +void repl() { + Interpreter interp; + std::string line; + std::cout << "OuroLang REPL (type 'exit' to quit)\n"; + while (true) { + std::cout << "> "; + std::getline(std::cin, line); + if (line == "exit") break; + try { + interp.run(line); + } catch (const std::exception &e) { + std::cerr << "Error: " << e.what() << std::endl; + } + } +} + +int main() { + repl(); + return 0; +} diff --git a/src/main.zig b/src/main.zig index 1fd2b3fdf..60f269309 100644 --- a/src/main.zig +++ b/src/main.zig @@ -40,59 +40,44 @@ pub fn main(init: std.process.Init) !void { return; } - std.debug.print("Unknown command: {s}\n", .{command}); - printHelp(); -} - -fn printHelp() void { - const help_text = - \\ABI Framework CLI - \\ - \\Usage: - \\ abi [options] - \\ - \\Commands: - \\ help, --help, -h Show this help message - \\ version, --version Show framework version - \\ info, system-info Show framework information and available features - \\ - \\For the full CLI (including tui), build the tools/cli entrypoint. - \\For more advanced usage, see the examples/ directory. - ; - std.debug.print("{s}\n", .{help_text}); -} - -fn printFrameworkInfo(allocator: std.mem.Allocator) !void { - std.debug.print("=== ABI Framework Information ===\n", .{}); - std.debug.print("Version: {s}\n", .{abi.version()}); - std.debug.print("SIMD Support: {s}\n", .{if (abi.hasSimdSupport()) "Yes" else "No"}); - - // Initialise the shared I/O backend (Zig 0.16) - var io_backend = try IoBackend.init(allocator); - defer io_backend.deinit(); - - // Build a fully‑featured framework using the builder pattern. - var builder = abi.App.builder(allocator); - _ = builder.withDefault(.gpu); - _ = builder.withDefault(.ai); - _ = builder.withDefault(.database); - _ = builder.withDefault(.web); - _ = builder.withDefault(.network); - _ = builder.withDefault(.observability); - _ = builder.withIo(io_backend.io); - var framework = builder.build() catch |err| { - std.debug.print("Framework initialization failed: {t}\n", .{err}); - std.debug.print("Running with minimal features...\n", .{}); - - // Minimal framework – builder without any feature defaults. - var minimal_builder = abi.App.builder(allocator); - var minimal_framework = try minimal_builder.build(); - defer abi.shutdown(&minimal_framework); - - std.debug.print("Minimal framework initialized successfully\n", .{}); - return; - }; - defer abi.shutdown(&framework); +pub const Error = error{ + EmptyText, + BlacklistedWord, + TextTooLong, + InvalidValues, + ProcessingFailed, +}; + +pub const Request = struct { + text: []const u8, + values: []const usize, + + pub fn validate(self: Request) Error!void { + if (self.text.len == 0) return Error.EmptyText; + if (self.values.len == 0) return Error.InvalidValues; + _ = try Abbey.checkCompliance(self.text); + } +}; + +pub const Response = struct { + result: usize, + message: []const u8, +}; + +pub const ComplianceError = error{ + EmptyText, + BlacklistedWord, + TextTooLong, +}; + +/// Abbey persona: ensures simple ethical compliance +pub const Abbey = struct { + const MAX_TEXT_LENGTH = 1000; + const BLACKLISTED_WORDS = [_][]const u8{ "bad", "evil", "hate" }; + + pub fn isCompliant(text: []const u8) bool { + return checkCompliance(text) catch return false; + } std.debug.print("Framework initialized successfully\n", .{}); @@ -126,3 +111,10 @@ fn printFrameworkInfo(allocator: std.mem.Allocator) !void { std.debug.print("Network: Not available (enable with -Denable-network=true)\n", .{}); } } + +test "Abi orchestrates personas" { + const req = Request{ .text = "ok", .values = &[_]usize{ 1, 2 } }; + const res = try Abi.process(req); + try std.testing.expectEqual(@as(usize, 3), res.result); + try std.testing.expectEqualStrings("Computation successful", res.message); +}