Fun 0.41.5
The programming language that makes You have fun
Loading...
Searching...
No Matches
fun.c
Go to the documentation of this file.
1/*
2 * This file is part of the Fun programming language.
3 * https://fun-lang.xyz/
4 *
5 * Copyright 2025 Johannes Findeisen <you@hanez.org>
6 * Licensed under the terms of the Apache-2.0 license.
7 * https://opensource.org/license/apache-2-0
8 */
9
18
19#include "bytecode.h"
20#include "parser.h"
21#include "vm.h"
22#include <stdarg.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#ifdef FUN_WITH_REPL
28#include "repl.h"
29#endif
30
31#ifndef FUN_VERSION
32#define FUN_VERSION "0.0.0-dev"
33#endif
34
43static void print_usage(const char *prog) {
44 printf("Fun %s\n", FUN_VERSION);
45 printf("Usage:\n");
46#ifdef FUN_WITH_REPL
47 printf(" %s [--trace|-t] [--repl-on-error] [script.fun]\n", prog ? prog : "fun");
48 printf(" %s --help | -h\n", prog ? prog : "fun");
49 printf(" %s --version | -V\n", prog ? prog : "fun");
50 printf("\n");
51 printf("Options:\n");
52 printf(" --trace, -t Print executed ops and stack tops during run\n");
53 printf(" --repl-on-error Enter interactive REPL on runtime error with stack preserved\n\n");
54 printf("When no script is provided, a REPL starts. Submit an empty line to execute the buffer.\n");
55#else
56 printf(" %s [--trace|-t] <script.fun>\n", prog ? prog : "fun");
57 printf(" %s --help | -h\n", prog ? prog : "fun");
58 printf(" %s --version | -V\n", prog ? prog : "fun");
59 printf("\n");
60 printf("Options:\n --trace, -t Print executed ops and stack tops during run\n\n");
61 printf("REPL is disabled in this build. Please provide a script file to run.\n");
62#endif
63}
64
76int main(int argc, char **argv) {
77 /* Set FUN_EXECUTABLE environment variable to the path of this binary */
78 setenv("FUN_EXECUTABLE", argv[0], 1);
79
80 VM vm;
81 vm_init(&vm);
82
83 int argi = 1;
84 for (; argi < argc; ++argi) {
85 const char *arg = argv[argi];
86 if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
87 print_usage(argv[0]);
88 return 0;
89 }
90 if (strcmp(arg, "--version") == 0 || strcmp(arg, "-V") == 0) {
91 printf("Fun %s\n", FUN_VERSION);
92 return 0;
93 }
94 if (strcmp(arg, "--trace") == 0 || strcmp(arg, "-t") == 0) {
95 vm.trace_enabled = 1;
96 continue;
97 }
98#ifdef FUN_WITH_REPL
99 if (strcmp(arg, "--repl-on-error") == 0) {
100 vm.repl_on_error = 1;
101 vm.on_error_repl = fun_run_repl; /* provide REPL entry to core VM */
102 continue;
103 }
104#endif
105 /* first non-option assumed to be script path */
106 break;
107 }
108
109#ifndef FUN_WITH_REPL
110 if (argi >= argc) {
111 fprintf(stderr, "Error: REPL is disabled. Please provide a script to run.\n");
112 print_usage(argv[0]);
113 return 2;
114 }
115#endif
116
117 if (argi < argc) {
118 const char *path = argv[argi];
119
120 /* Collect script arguments (everything after script path) and expose via env vars */
121 int sargi = argi + 1; /* first script arg following the script path */
122 int sargc = (sargi < argc) ? (argc - sargi) : 0;
123
124 /* Export FUN_ARGC */
125 {
126 char buf[32];
127 snprintf(buf, sizeof(buf), "%d", sargc);
128 setenv("FUN_ARGC", buf, 1);
129 }
130
131 /* Export FUN_ARGV_i */
132 for (int i = 0; i < sargc; ++i) {
133 char key[32];
134 snprintf(key, sizeof(key), "FUN_ARGV_%d", i);
135 setenv(key, argv[sargi + i], 1);
136 }
137
138 /* Optional: space-joined convenience string FUN_ARGS */
139 if (sargc > 0) {
140 size_t total = 0;
141 for (int i = 0; i < sargc; ++i) {
142 total += strlen(argv[sargi + i]) + 1; /* +1 for space or NUL */
143 }
144 char *joined = (char *)malloc(total);
145 if (joined) {
146 joined[0] = '\0';
147 for (int i = 0; i < sargc; ++i) {
148 strcat(joined, argv[sargi + i]);
149 if (i + 1 < sargc) strcat(joined, " ");
150 }
151 setenv("FUN_ARGS", joined, 1);
152 free(joined);
153 }
154 } else {
155 /* Ensure FUN_ARGS is at least cleared for consistency */
156 setenv("FUN_ARGS", "", 1);
157 }
158
160 if (!bc) {
161 fprintf(stderr, "Failed to compile script: %s\n", path);
162 return 1;
163 }
164
165 vm_run(&vm, bc);
166 vm_print_output(&vm);
167 vm_clear_output(&vm);
168 bytecode_free(bc);
169 return vm.exit_code;
170 }
171
172#ifdef FUN_WITH_REPL
173 return fun_run_repl(&vm);
174#else
175 fprintf(stderr, "Internal error: REPL not available in this build.\n");
176 return 2;
177#endif
178}
void bytecode_free(Bytecode *bc)
Free a Bytecode and all memory it owns.
Definition bytecode.c:92
Definitions for the Fun VM bytecode: opcodes, instruction format, and bytecode container API.
#define FUN_VERSION
Definition fun.c:32
int main(void)
Build and execute a demo bytecode program and print results.
Definition fun_test.c:44
char * buf
Definition input_line.c:103
free(vals)
Bytecode * parse_file_to_bytecode(const char *path)
Parse a .fun source file and return compiled bytecode.
Definition parser.c:7529
Public API for parsing Fun source into bytecode.
Interactive Read-Eval-Print Loop (REPL) entry point.
The Fun virtual machine state.
Definition vm.h:110
int repl_on_error
Definition vm.h:130
int(* on_error_repl)(struct VM *vm)
Definition vm.h:131
int trace_enabled
Definition vm.h:129
int exit_code
Definition vm.h:127
void vm_init(VM *vm)
Initialize a VM instance to its default state.
Definition vm.c:714
#define fprintf
Definition vm.c:200
void vm_clear_output(VM *vm)
Clear the VM's buffered output values and partial flags.
Definition vm.c:349
void vm_print_output(VM *vm)
Print the VM's buffered output values to stdout.
Definition vm.c:797
Core virtual machine data structures and public VM API.
void vm_run(VM *vm, Bytecode *entry)
Execute the provided entry bytecode in the VM. Pushes an initial frame and runs until HALT or an unre...
Value path
Definition write_file.c:33