fortrangoingonforty/fortbite / f31e787

Browse files

heh, oops:

Authored by espadonne
SHA
f31e787c6e0d4d672298fb87b6e88e1ef26be75f
Parents
9d83da1
Tree
c92440b

41 changed files

StatusFile+-
D src/cli/completion.c 0 1
D src/cli/display.c 0 1
D src/cli/history.c 0 1
D src/cli/interface.c 0 1
D src/config/config.c 0 1
D src/config/defaults.c 0 1
D src/config/validation.c 0 1
D src/core/engine.c 0 1
D src/core/main.c 0 176
D src/core/memory.c 0 72
D src/core/types.c 0 202
D src/export/csv.c 0 1
D src/export/formats.c 0 1
D src/export/json.c 0 1
D src/export/latex.c 0 1
A src/fortbite.f90 21 0
A src/fortbite_arithmetic_m.f90 227 0
A src/fortbite_io_m.f90 267 0
A src/fortbite_precision_m.f90 116 0
A src/fortbite_types_m.f90 293 0
D src/math/arithmetic.c 0 1
D src/math/complex.c 0 1
D src/math/functions.c 0 1
D src/math/matrix.c 0 1
D src/math/precision.c 0 1
D src/parser/ast.c 0 1
D src/parser/lexer.c 0 258
D src/parser/parser.c 0 1
D src/parser/syntax.c 0 1
D src/plotting/ascii_plot.c 0 1
D src/plotting/data.c 0 1
D src/plotting/export.c 0 1
D src/plugins/api.c 0 1
D src/plugins/loader.c 0 1
D src/plugins/registry.c 0 1
D src/units/converter.c 0 1
D src/units/database.c 0 1
D src/units/parser.c 0 1
D src/utils/debug.c 0 1
D src/utils/file.c 0 1
D src/utils/string.c 0 1
src/cli/completion.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/cli/display.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/cli/history.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/cli/interface.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/config/config.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/config/defaults.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/config/validation.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/core/engine.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/core/main.cdeleted
@@ -1,176 +0,0 @@
1
-#include "fortbite.h"
2
-#include <stdio.h>
3
-#include <stdlib.h>
4
-#include <readline/readline.h>
5
-#include <readline/history.h>
6
-
7
-struct fortbite_context {
8
-    fortbite_variable_t* variables;
9
-    int default_precision;
10
-    bool verbose;
11
-};
12
-
13
-fortbite_context_t* fortbite_context_new(void) {
14
-    fortbite_context_t* ctx = fortbite_malloc(sizeof(fortbite_context_t));
15
-    ctx->variables = NULL;
16
-    ctx->default_precision = DEFAULT_PRECISION;
17
-    ctx->verbose = false;
18
-    return ctx;
19
-}
20
-
21
-void fortbite_context_free(fortbite_context_t* ctx) {
22
-    if (!ctx) return;
23
-    
24
-    fortbite_variable_t* var = ctx->variables;
25
-    while (var) {
26
-        fortbite_variable_t* next = var->next;
27
-        fortbite_variable_free(var);
28
-        var = next;
29
-    }
30
-    
31
-    fortbite_free(ctx);
32
-}
33
-
34
-static void print_banner(void) {
35
-    printf("FORTBITE v%s - High Precision Calculator\n", FORTBITE_VERSION);
36
-    printf("Type 'help' for commands or 'exit' to quit.\n");
37
-    printf("Use :: for precision specification (e.g., 3.14159::100)\n");
38
-    printf("Use := for variable assignment (e.g., x := 42)\n\n");
39
-}
40
-
41
-static void print_help(void) {
42
-    printf("FORTBITE Commands:\n");
43
-    printf("  Basic arithmetic: +, -, *, /, ^ (power), %% (modulo)\n");
44
-    printf("  Variables: x := value\n");
45
-    printf("  Precision: value::digits\n");
46
-    printf("  Complex: 3+4i, cis(angle)\n");
47
-    printf("  Functions: sin, cos, tan, log, exp, sqrt, abs\n");
48
-    printf("  Constants: pi, e, i\n");
49
-    printf("  Commands: help, exit, clear\n");
50
-    printf("  Arrow keys: command history\n\n");
51
-}
52
-
53
-static bool process_command(fortbite_context_t* ctx, const char* input) {
54
-    if (!input || strlen(input) == 0) {
55
-        return true;
56
-    }
57
-    
58
-    char* line = fortbite_strdup(input);
59
-    char* trimmed = line;
60
-    
61
-    while (*trimmed && isspace(*trimmed)) trimmed++;
62
-    
63
-    if (strcmp(trimmed, "exit") == 0 || strcmp(trimmed, "quit") == 0) {
64
-        fortbite_free(line);
65
-        return false;
66
-    }
67
-    
68
-    if (strcmp(trimmed, "help") == 0) {
69
-        print_help();
70
-        fortbite_free(line);
71
-        return true;
72
-    }
73
-    
74
-    if (strcmp(trimmed, "clear") == 0) {
75
-        system("clear");
76
-        fortbite_free(line);
77
-        return true;
78
-    }
79
-    
80
-    if (strncmp(trimmed, "precision", 9) == 0) {
81
-        char* precision_str = trimmed + 9;
82
-        while (*precision_str && isspace(*precision_str)) precision_str++;
83
-        if (*precision_str) {
84
-            int precision = atoi(precision_str);
85
-            if (precision > 0 && precision <= 10000) {
86
-                ctx->default_precision = precision;
87
-                printf("Default precision set to %d bits\n", precision);
88
-            } else {
89
-                printf("Invalid precision. Use 1-10000.\n");
90
-            }
91
-        } else {
92
-            printf("Current default precision: %d bits\n", ctx->default_precision);
93
-        }
94
-        fortbite_free(line);
95
-        return true;
96
-    }
97
-    
98
-    fortbite_token_t* tokens = fortbite_tokenize(trimmed);
99
-    if (!tokens) {
100
-        printf("Error: Failed to tokenize input\n");
101
-        fortbite_free(line);
102
-        return true;
103
-    }
104
-    
105
-    if (tokens[0].type == TOKEN_ERROR) {
106
-        printf("Error: Invalid token '%s' at position %zu\n", 
107
-               tokens[0].value ? tokens[0].value : "unknown", tokens[0].position);
108
-    } else {
109
-        printf("Parsed tokens: ");
110
-        for (size_t i = 0; tokens[i].type != TOKEN_EOF; i++) {
111
-            printf("[%s:%s] ", 
112
-                   tokens[i].type == TOKEN_NUMBER ? "NUM" :
113
-                   tokens[i].type == TOKEN_IDENTIFIER ? "ID" :
114
-                   tokens[i].type == TOKEN_OPERATOR ? "OP" :
115
-                   tokens[i].type == TOKEN_ASSIGN ? "ASSIGN" :
116
-                   tokens[i].type == TOKEN_PRECISION ? "PREC" : "OTHER",
117
-                   tokens[i].value ? tokens[i].value : "");
118
-        }
119
-        printf("\n");
120
-    }
121
-    
122
-    fortbite_tokens_free(tokens);
123
-    fortbite_free(line);
124
-    return true;
125
-}
126
-
127
-int fortbite_init(void) {
128
-    mpfr_set_default_prec(DEFAULT_PRECISION);
129
-    return 0;
130
-}
131
-
132
-void fortbite_cleanup(void) {
133
-    mpfr_free_cache();
134
-}
135
-
136
-static void setup_readline(void) {
137
-    rl_bind_key('\t', rl_complete);
138
-}
139
-
140
-int main(void) {
141
-    if (fortbite_init() != 0) {
142
-        fprintf(stderr, "Failed to initialize FORTBITE\n");
143
-        return EXIT_FAILURE;
144
-    }
145
-    
146
-    fortbite_context_t* ctx = fortbite_context_new();
147
-    setup_readline();
148
-    print_banner();
149
-    
150
-    char* input;
151
-    bool running = true;
152
-    
153
-    while (running && (input = readline("fortbite> ")) != NULL) {
154
-        if (strlen(input) > 0) {
155
-            add_history(input);
156
-        }
157
-        
158
-        running = process_command(ctx, input);
159
-        free(input);
160
-    }
161
-    
162
-    if (!input) {
163
-        printf("\n");
164
-    }
165
-    
166
-    printf("Goodbye!\n");
167
-    
168
-    fortbite_context_free(ctx);
169
-    fortbite_cleanup();
170
-    
171
-#ifdef DEBUG
172
-    fortbite_memory_stats();
173
-#endif
174
-    
175
-    return EXIT_SUCCESS;
176
-}
src/core/memory.cdeleted
@@ -1,72 +0,0 @@
1
-#include "fortbite.h"
2
-#include <stdlib.h>
3
-#include <string.h>
4
-#include <stdio.h>
5
-
6
-#ifdef DEBUG
7
-static size_t memory_allocated = 0;
8
-static size_t memory_freed = 0;
9
-#endif
10
-
11
-void* fortbite_malloc(size_t size) {
12
-    void* ptr = malloc(size);
13
-    if (!ptr) {
14
-        fprintf(stderr, "FORTBITE: Memory allocation failed for %zu bytes\n", size);
15
-        exit(EXIT_FAILURE);
16
-    }
17
-    
18
-#ifdef DEBUG
19
-    memory_allocated += size;
20
-#endif
21
-    
22
-    return ptr;
23
-}
24
-
25
-void* fortbite_calloc(size_t count, size_t size) {
26
-    void* ptr = calloc(count, size);
27
-    if (!ptr) {
28
-        fprintf(stderr, "FORTBITE: Memory allocation failed for %zu * %zu bytes\n", count, size);
29
-        exit(EXIT_FAILURE);
30
-    }
31
-    
32
-#ifdef DEBUG
33
-    memory_allocated += count * size;
34
-#endif
35
-    
36
-    return ptr;
37
-}
38
-
39
-void* fortbite_realloc(void* ptr, size_t size) {
40
-    void* new_ptr = realloc(ptr, size);
41
-    if (!new_ptr && size > 0) {
42
-        fprintf(stderr, "FORTBITE: Memory reallocation failed for %zu bytes\n", size);
43
-        exit(EXIT_FAILURE);
44
-    }
45
-    
46
-    return new_ptr;
47
-}
48
-
49
-void fortbite_free(void* ptr) {
50
-    if (ptr) {
51
-        free(ptr);
52
-#ifdef DEBUG
53
-        memory_freed++;
54
-#endif
55
-    }
56
-}
57
-
58
-char* fortbite_strdup(const char* str) {
59
-    if (!str) return NULL;
60
-    
61
-    size_t len = strlen(str) + 1;
62
-    char* copy = fortbite_malloc(len);
63
-    memcpy(copy, str, len);
64
-    return copy;
65
-}
66
-
67
-#ifdef DEBUG
68
-void fortbite_memory_stats(void) {
69
-    printf("Memory allocated: %zu bytes\n", memory_allocated);
70
-    printf("Memory freed: %zu objects\n", memory_freed);
71
-}
72
-#endif
src/core/types.cdeleted
@@ -1,202 +0,0 @@
1
-#include "fortbite.h"
2
-
3
-fortbite_value_t* fortbite_value_new(fortbite_type_t type) {
4
-    fortbite_value_t* value = fortbite_malloc(sizeof(fortbite_value_t));
5
-    value->type = type;
6
-    
7
-    switch (type) {
8
-        case FORTBITE_TYPE_SCALAR:
9
-            fortbite_scalar_new_init(&value->data.scalar, DEFAULT_PRECISION);
10
-            break;
11
-        case FORTBITE_TYPE_COMPLEX:
12
-            fortbite_complex_new_init(&value->data.complex, DEFAULT_PRECISION);
13
-            break;
14
-        case FORTBITE_TYPE_MATRIX:
15
-            value->data.matrix.rows = 0;
16
-            value->data.matrix.cols = 0;
17
-            value->data.matrix.data = NULL;
18
-            value->data.matrix.is_sparse = false;
19
-            break;
20
-        case FORTBITE_TYPE_UNIT:
21
-            value->data.quantity.unit = NULL;
22
-            fortbite_complex_new_init(&value->data.quantity.value, DEFAULT_PRECISION);
23
-            break;
24
-        default:
25
-            break;
26
-    }
27
-    
28
-    return value;
29
-}
30
-
31
-void fortbite_value_free(fortbite_value_t* value) {
32
-    if (!value) return;
33
-    
34
-    switch (value->type) {
35
-        case FORTBITE_TYPE_SCALAR:
36
-            fortbite_scalar_clear(&value->data.scalar);
37
-            break;
38
-        case FORTBITE_TYPE_COMPLEX:
39
-            fortbite_complex_clear(&value->data.complex);
40
-            break;
41
-        case FORTBITE_TYPE_MATRIX:
42
-            fortbite_matrix_clear(&value->data.matrix);
43
-            break;
44
-        case FORTBITE_TYPE_UNIT:
45
-            fortbite_complex_clear(&value->data.quantity.value);
46
-            break;
47
-        default:
48
-            break;
49
-    }
50
-    
51
-    fortbite_free(value);
52
-}
53
-
54
-fortbite_value_t* fortbite_value_copy(const fortbite_value_t* value) {
55
-    if (!value) return NULL;
56
-    
57
-    fortbite_value_t* copy = fortbite_value_new(value->type);
58
-    
59
-    switch (value->type) {
60
-        case FORTBITE_TYPE_SCALAR:
61
-            fortbite_scalar_set(&copy->data.scalar, &value->data.scalar);
62
-            break;
63
-        case FORTBITE_TYPE_COMPLEX:
64
-            fortbite_complex_set(&copy->data.complex, &value->data.complex);
65
-            break;
66
-        case FORTBITE_TYPE_MATRIX:
67
-            if (value->data.matrix.data) {
68
-                copy->data.matrix = fortbite_matrix_copy(&value->data.matrix);
69
-            }
70
-            break;
71
-        case FORTBITE_TYPE_UNIT:
72
-            fortbite_complex_set(&copy->data.quantity.value, &value->data.quantity.value);
73
-            copy->data.quantity.unit = value->data.quantity.unit;
74
-            break;
75
-        default:
76
-            break;
77
-    }
78
-    
79
-    return copy;
80
-}
81
-
82
-void fortbite_scalar_new_init(fortbite_scalar_t* scalar, int precision) {
83
-    mpfr_init2(scalar->value, precision);
84
-    scalar->precision = precision;
85
-}
86
-
87
-void fortbite_scalar_clear(fortbite_scalar_t* scalar) {
88
-    mpfr_clear(scalar->value);
89
-}
90
-
91
-void fortbite_scalar_set_d(fortbite_scalar_t* scalar, double value) {
92
-    mpfr_set_d(scalar->value, value, MPFR_RNDN);
93
-}
94
-
95
-void fortbite_scalar_set_str(fortbite_scalar_t* scalar, const char* str, int base) {
96
-    mpfr_set_str(scalar->value, str, base, MPFR_RNDN);
97
-}
98
-
99
-void fortbite_scalar_set(fortbite_scalar_t* dest, const fortbite_scalar_t* src) {
100
-    mpfr_set(dest->value, src->value, MPFR_RNDN);
101
-    dest->precision = src->precision;
102
-}
103
-
104
-void fortbite_complex_new_init(fortbite_complex_t* complex, int precision) {
105
-    fortbite_scalar_new_init(&complex->real, precision);
106
-    fortbite_scalar_new_init(&complex->imag, precision);
107
-}
108
-
109
-void fortbite_complex_clear(fortbite_complex_t* complex) {
110
-    fortbite_scalar_clear(&complex->real);
111
-    fortbite_scalar_clear(&complex->imag);
112
-}
113
-
114
-void fortbite_complex_set(fortbite_complex_t* dest, const fortbite_complex_t* src) {
115
-    fortbite_scalar_set(&dest->real, &src->real);
116
-    fortbite_scalar_set(&dest->imag, &src->imag);
117
-}
118
-
119
-fortbite_matrix_t fortbite_matrix_new(size_t rows, size_t cols, int precision) {
120
-    fortbite_matrix_t matrix;
121
-    matrix.rows = rows;
122
-    matrix.cols = cols;
123
-    matrix.is_sparse = false;
124
-    
125
-    if (rows > 0 && cols > 0) {
126
-        matrix.data = fortbite_malloc(rows * sizeof(fortbite_complex_t*));
127
-        for (size_t i = 0; i < rows; i++) {
128
-            matrix.data[i] = fortbite_malloc(cols * sizeof(fortbite_complex_t));
129
-            for (size_t j = 0; j < cols; j++) {
130
-                fortbite_complex_new_init(&matrix.data[i][j], precision);
131
-            }
132
-        }
133
-    } else {
134
-        matrix.data = NULL;
135
-    }
136
-    
137
-    return matrix;
138
-}
139
-
140
-void fortbite_matrix_clear(fortbite_matrix_t* matrix) {
141
-    if (matrix->data) {
142
-        for (size_t i = 0; i < matrix->rows; i++) {
143
-            for (size_t j = 0; j < matrix->cols; j++) {
144
-                fortbite_complex_clear(&matrix->data[i][j]);
145
-            }
146
-            fortbite_free(matrix->data[i]);
147
-        }
148
-        fortbite_free(matrix->data);
149
-        matrix->data = NULL;
150
-    }
151
-    matrix->rows = 0;
152
-    matrix->cols = 0;
153
-}
154
-
155
-fortbite_matrix_t fortbite_matrix_copy(const fortbite_matrix_t* src) {
156
-    fortbite_matrix_t copy = fortbite_matrix_new(src->rows, src->cols, DEFAULT_PRECISION);
157
-    copy.is_sparse = src->is_sparse;
158
-    
159
-    if (src->data) {
160
-        for (size_t i = 0; i < src->rows; i++) {
161
-            for (size_t j = 0; j < src->cols; j++) {
162
-                fortbite_complex_set(&copy.data[i][j], &src->data[i][j]);
163
-            }
164
-        }
165
-    }
166
-    
167
-    return copy;
168
-}
169
-
170
-fortbite_complex_t* fortbite_matrix_get(const fortbite_matrix_t* matrix, size_t row, size_t col) {
171
-    if (!matrix->data || row >= matrix->rows || col >= matrix->cols) {
172
-        return NULL;
173
-    }
174
-    return &matrix->data[row][col];
175
-}
176
-
177
-void fortbite_matrix_set(fortbite_matrix_t* matrix, size_t row, size_t col, const fortbite_complex_t* value) {
178
-    if (!matrix->data || row >= matrix->rows || col >= matrix->cols) {
179
-        return;
180
-    }
181
-    fortbite_complex_set(&matrix->data[row][col], value);
182
-}
183
-
184
-fortbite_variable_t* fortbite_variable_new(const char* name, const fortbite_value_t* value) {
185
-    fortbite_variable_t* var = fortbite_malloc(sizeof(fortbite_variable_t));
186
-    var->name = fortbite_strdup(name);
187
-    if (value) {
188
-        var->value = *fortbite_value_copy(value);
189
-    } else {
190
-        var->value.type = FORTBITE_TYPE_UNDEFINED;
191
-    }
192
-    var->next = NULL;
193
-    return var;
194
-}
195
-
196
-void fortbite_variable_free(fortbite_variable_t* var) {
197
-    if (!var) return;
198
-    
199
-    fortbite_free(var->name);
200
-    fortbite_value_free(&var->value);
201
-    fortbite_free(var);
202
-}
src/export/csv.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/export/formats.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/export/json.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/export/latex.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/fortbite.f90added
@@ -0,0 +1,21 @@
1
+!> FORTBITE - High-Precision Calculator in Modern Fortran
2
+!>
3
+!> A powerful mathematical calculator leveraging Fortran's strengths in
4
+!> scientific computing, with arbitrary precision arithmetic, complex numbers,
5
+!> matrix operations, and extensive mathematical functions.
6
+!>
7
+!> Author: espadonne (mfw)
8
+!> License: MIT
9
+program fortbite
10
+    use fortbite_precision_m, only: set_default_precision
11
+    use fortbite_types_m, only: value_t
12
+    use fortbite_io_m, only: repl_loop
13
+    implicit none
14
+    
15
+    ! Initialize default precision
16
+    call set_default_precision(15)  ! Start with ~double precision
17
+    
18
+    ! Start the main REPL loop
19
+    call repl_loop()
20
+    
21
+end program fortbite
src/fortbite_arithmetic_m.f90added
@@ -0,0 +1,227 @@
1
+!> Basic arithmetic operations module for FORTBITE
2
+!>
3
+!> Provides arithmetic operations for scalars, complex numbers, and matrices
4
+!> with proper precision handling and type promotion.
5
+module fortbite_arithmetic_m
6
+    use iso_fortran_env, only: real64
7
+    use fortbite_types_m, only: value_t, VALUE_SCALAR, VALUE_COMPLEX, VALUE_MATRIX, &
8
+                               create_scalar, create_complex, is_real
9
+    implicit none
10
+    private
11
+    
12
+    public :: add_values, subtract_values, multiply_values, divide_values, power_values
13
+    public :: negate_value, abs_value
14
+    
15
+contains
16
+
17
+    !> Add two values
18
+    function add_values(a, b) result(c)
19
+        type(value_t), intent(in) :: a, b
20
+        type(value_t) :: c
21
+        
22
+        ! Handle scalar + scalar
23
+        if (a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_SCALAR) then
24
+            c = create_scalar(a%scalar_val + b%scalar_val)
25
+            return
26
+        end if
27
+        
28
+        ! Handle mixed scalar/complex operations
29
+        if ((a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_COMPLEX) .or. &
30
+            (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_SCALAR)) then
31
+            
32
+            if (a%value_type == VALUE_SCALAR) then
33
+                c = create_complex(a%scalar_val + real(b%complex_val), aimag(b%complex_val))
34
+            else
35
+                c = create_complex(real(a%complex_val) + b%scalar_val, aimag(a%complex_val))
36
+            end if
37
+            return
38
+        end if
39
+        
40
+        ! Handle complex + complex
41
+        if (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_COMPLEX) then
42
+            c = create_complex(real(a%complex_val) + real(b%complex_val), &
43
+                              aimag(a%complex_val) + aimag(b%complex_val))
44
+            return
45
+        end if
46
+        
47
+        ! TODO: Handle matrix operations in Phase 3
48
+        ! For now, return undefined for unsupported operations
49
+        c%value_type = 0  ! VALUE_UNDEFINED
50
+    end function add_values
51
+    
52
+    !> Subtract two values
53
+    function subtract_values(a, b) result(c)
54
+        type(value_t), intent(in) :: a, b
55
+        type(value_t) :: c
56
+        
57
+        ! Handle scalar - scalar
58
+        if (a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_SCALAR) then
59
+            c = create_scalar(a%scalar_val - b%scalar_val)
60
+            return
61
+        end if
62
+        
63
+        ! Handle mixed scalar/complex operations
64
+        if ((a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_COMPLEX) .or. &
65
+            (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_SCALAR)) then
66
+            
67
+            if (a%value_type == VALUE_SCALAR) then
68
+                c = create_complex(a%scalar_val - real(b%complex_val), -aimag(b%complex_val))
69
+            else
70
+                c = create_complex(real(a%complex_val) - b%scalar_val, aimag(a%complex_val))
71
+            end if
72
+            return
73
+        end if
74
+        
75
+        ! Handle complex - complex
76
+        if (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_COMPLEX) then
77
+            c = create_complex(real(a%complex_val) - real(b%complex_val), &
78
+                              aimag(a%complex_val) - aimag(b%complex_val))
79
+            return
80
+        end if
81
+        
82
+        c%value_type = 0  ! VALUE_UNDEFINED
83
+    end function subtract_values
84
+    
85
+    !> Multiply two values
86
+    function multiply_values(a, b) result(c)
87
+        type(value_t), intent(in) :: a, b
88
+        type(value_t) :: c
89
+        
90
+        ! Handle scalar * scalar
91
+        if (a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_SCALAR) then
92
+            c = create_scalar(a%scalar_val * b%scalar_val)
93
+            return
94
+        end if
95
+        
96
+        ! Handle mixed scalar/complex operations
97
+        if ((a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_COMPLEX) .or. &
98
+            (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_SCALAR)) then
99
+            
100
+            if (a%value_type == VALUE_SCALAR) then
101
+                c = create_complex(a%scalar_val * real(b%complex_val), &
102
+                                 a%scalar_val * aimag(b%complex_val))
103
+            else
104
+                c = create_complex(real(a%complex_val) * b%scalar_val, &
105
+                                 aimag(a%complex_val) * b%scalar_val)
106
+            end if
107
+            return
108
+        end if
109
+        
110
+        ! Handle complex * complex
111
+        if (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_COMPLEX) then
112
+            c%complex_val = a%complex_val * b%complex_val
113
+            c%value_type = VALUE_COMPLEX
114
+            return
115
+        end if
116
+        
117
+        c%value_type = 0  ! VALUE_UNDEFINED
118
+    end function multiply_values
119
+    
120
+    !> Divide two values
121
+    function divide_values(a, b) result(c)
122
+        type(value_t), intent(in) :: a, b
123
+        type(value_t) :: c
124
+        
125
+        ! Handle scalar / scalar
126
+        if (a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_SCALAR) then
127
+            if (abs(b%scalar_val) < epsilon(b%scalar_val)) then
128
+                write(*, '(A)') 'Error: Division by zero'
129
+                c%value_type = 0  ! VALUE_UNDEFINED
130
+                return
131
+            end if
132
+            c = create_scalar(a%scalar_val / b%scalar_val)
133
+            return
134
+        end if
135
+        
136
+        ! Handle mixed scalar/complex operations
137
+        if ((a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_COMPLEX) .or. &
138
+            (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_SCALAR)) then
139
+            
140
+            if (a%value_type == VALUE_SCALAR) then
141
+                if (abs(b%complex_val) < epsilon(real(b%complex_val))) then
142
+                    write(*, '(A)') 'Error: Division by zero'
143
+                    c%value_type = 0
144
+                    return
145
+                end if
146
+                c%complex_val = a%scalar_val / b%complex_val
147
+                c%value_type = VALUE_COMPLEX
148
+            else
149
+                if (abs(b%scalar_val) < epsilon(b%scalar_val)) then
150
+                    write(*, '(A)') 'Error: Division by zero'
151
+                    c%value_type = 0
152
+                    return
153
+                end if
154
+                c = create_complex(real(a%complex_val) / b%scalar_val, &
155
+                                 aimag(a%complex_val) / b%scalar_val)
156
+            end if
157
+            return
158
+        end if
159
+        
160
+        ! Handle complex / complex
161
+        if (a%value_type == VALUE_COMPLEX .and. b%value_type == VALUE_COMPLEX) then
162
+            if (abs(b%complex_val) < epsilon(real(b%complex_val))) then
163
+                write(*, '(A)') 'Error: Division by zero'
164
+                c%value_type = 0
165
+                return
166
+            end if
167
+            c%complex_val = a%complex_val / b%complex_val
168
+            c%value_type = VALUE_COMPLEX
169
+            return
170
+        end if
171
+        
172
+        c%value_type = 0  ! VALUE_UNDEFINED
173
+    end function divide_values
174
+    
175
+    !> Raise a value to a power
176
+    function power_values(a, b) result(c)
177
+        type(value_t), intent(in) :: a, b
178
+        type(value_t) :: c
179
+        
180
+        ! Handle scalar ** scalar
181
+        if (a%value_type == VALUE_SCALAR .and. b%value_type == VALUE_SCALAR) then
182
+            c = create_scalar(a%scalar_val ** b%scalar_val)
183
+            return
184
+        end if
185
+        
186
+        ! Handle complex exponentiation (more complex, implement later)
187
+        ! For now, convert to complex and use Fortran's intrinsic
188
+        if (a%value_type == VALUE_COMPLEX .or. b%value_type == VALUE_COMPLEX) then
189
+            write(*, '(A)') 'Complex exponentiation not yet fully implemented'
190
+            c%value_type = 0
191
+            return
192
+        end if
193
+        
194
+        c%value_type = 0  ! VALUE_UNDEFINED
195
+    end function power_values
196
+    
197
+    !> Negate a value
198
+    function negate_value(a) result(c)
199
+        type(value_t), intent(in) :: a
200
+        type(value_t) :: c
201
+        
202
+        select case (a%value_type)
203
+        case (VALUE_SCALAR)
204
+            c = create_scalar(-a%scalar_val)
205
+        case (VALUE_COMPLEX)
206
+            c = create_complex(-real(a%complex_val), -aimag(a%complex_val))
207
+        case default
208
+            c%value_type = 0  ! VALUE_UNDEFINED
209
+        end select
210
+    end function negate_value
211
+    
212
+    !> Absolute value of a value
213
+    function abs_value(a) result(c)
214
+        type(value_t), intent(in) :: a
215
+        type(value_t) :: c
216
+        
217
+        select case (a%value_type)
218
+        case (VALUE_SCALAR)
219
+            c = create_scalar(abs(a%scalar_val))
220
+        case (VALUE_COMPLEX)
221
+            c = create_scalar(abs(a%complex_val))
222
+        case default
223
+            c%value_type = 0  ! VALUE_UNDEFINED
224
+        end select
225
+    end function abs_value
226
+    
227
+end module fortbite_arithmetic_m
src/fortbite_io_m.f90added
@@ -0,0 +1,267 @@
1
+!> I/O and REPL interface module for FORTBITE
2
+!>
3
+!> Handles user input/output, command processing, and the main REPL loop.
4
+module fortbite_io_m
5
+    use fortbite_precision_m, only: get_precision_info, precision_info_t
6
+    use iso_fortran_env, only: real32, real64, real128
7
+    use fortbite_types_m, only: value_t, variable_t, print_value
8
+    implicit none
9
+    private
10
+    
11
+    public :: repl_loop, print_banner, print_help
12
+    public :: parse_command, is_command
13
+    
14
+    ! Maximum input line length
15
+    integer, parameter :: MAX_LINE_LENGTH = 1000
16
+    
17
+contains
18
+
19
+    !> Print the FORTBITE banner
20
+    subroutine print_banner()
21
+        write(*, '(A)') ''
22
+        write(*, '(A)') '======================================'
23
+        write(*, '(A)') '              FORTBITE               '
24
+        write(*, '(A)') '     High-Precision Calculator       '
25
+        write(*, '(A)') '      Modern Fortran Edition         '
26
+        write(*, '(A)') '======================================'
27
+        write(*, '(A)') ''
28
+        write(*, '(A)') 'Type "help" for commands or "exit" to quit.'
29
+        write(*, '(A)') 'Use :: for precision (e.g., 3.14159::100)'
30
+        write(*, '(A)') 'Use := for assignment (e.g., x := 42)'
31
+        write(*, '(A)') ''
32
+    end subroutine print_banner
33
+    
34
+    !> Print help information
35
+    subroutine print_help()
36
+        type(precision_info_t) :: info
37
+        
38
+        write(*, '(A)') 'FORTBITE Commands:'
39
+        write(*, '(A)') '  Basic arithmetic: +, -, *, /, ** (power)'
40
+        write(*, '(A)') '  Variables: x := value'
41
+        write(*, '(A)') '  Precision: value::digits (e.g., pi::50)'
42
+        write(*, '(A)') '  Complex: 3+4i, (3,4), cmplx(3,4)'
43
+        write(*, '(A)') '  Functions: sin, cos, tan, log, exp, sqrt, abs'
44
+        write(*, '(A)') '  Constants: pi, e, i'
45
+        write(*, '(A)') '  Matrices: [1,2;3,4], zeros(3,3), ones(2,2)'
46
+        write(*, '(A)') '  Commands: help, exit, clear, precision, info'
47
+        write(*, '(A)') ''
48
+        
49
+        ! Show current precision info
50
+        info = get_precision_info(real64)
51
+        write(*, '(A,A)') 'Current precision: ', trim(info%name)
52
+        write(*, '(A,I0,A)') 'Decimal digits: ', info%decimal_digits, ''
53
+        write(*, '(A,I0,A)') 'Exponent range: ±', info%exponent_range, ''
54
+        write(*, '(A)') ''
55
+    end subroutine print_help
56
+    
57
+    !> Check if input is a command (starts with a letter)
58
+    logical function is_command(input)
59
+        character(len=*), intent(in) :: input
60
+        character(len=len_trim(input)) :: trimmed_input
61
+        
62
+        trimmed_input = trim(adjustl(input))
63
+        
64
+        if (len_trim(trimmed_input) == 0) then
65
+            is_command = .false.
66
+            return
67
+        end if
68
+        
69
+        ! Check if it starts with a letter (command) or digit/operator (expression)
70
+        is_command = (trimmed_input(1:1) >= 'a' .and. trimmed_input(1:1) <= 'z') .or. &
71
+                     (trimmed_input(1:1) >= 'A' .and. trimmed_input(1:1) <= 'Z')
72
+        
73
+        ! Special case: check for assignment (contains :=)
74
+        if (index(trimmed_input, ':=') > 0) then
75
+            is_command = .false.
76
+        end if
77
+    end function is_command
78
+    
79
+    !> Parse and execute a command
80
+    logical function parse_command(input, variables) result(continue_repl)
81
+        character(len=*), intent(in) :: input
82
+        type(variable_t), pointer, intent(inout) :: variables
83
+        
84
+        character(len=len_trim(input)) :: command
85
+        character(len=100) :: arg
86
+        integer :: space_pos
87
+        
88
+        continue_repl = .true.
89
+        command = trim(adjustl(input))
90
+        
91
+        ! Split command and arguments
92
+        space_pos = index(command, ' ')
93
+        if (space_pos > 0) then
94
+            arg = command(space_pos+1:)
95
+            command = command(1:space_pos-1)
96
+        else
97
+            arg = ''
98
+        end if
99
+        
100
+        ! Convert to lowercase for case-insensitive commands
101
+        call to_lowercase(command)
102
+        
103
+        select case (trim(command))
104
+        case ('help', 'h', '?')
105
+            call print_help()
106
+            
107
+        case ('exit', 'quit', 'q')
108
+            write(*, '(A)') 'Goodbye!'
109
+            continue_repl = .false.
110
+            
111
+        case ('clear', 'cls')
112
+            call clear_screen()
113
+            
114
+        case ('precision')
115
+            call handle_precision_command(arg)
116
+            
117
+        case ('info')
118
+            call show_system_info()
119
+            
120
+        case ('vars', 'variables')
121
+            call show_variables(variables)
122
+            
123
+        case default
124
+            write(*, '(A,A,A)') 'Unknown command: "', trim(command), '"'
125
+            write(*, '(A)') 'Type "help" for available commands.'
126
+        end select
127
+    end function parse_command
128
+    
129
+    !> Main REPL (Read-Eval-Print Loop)
130
+    subroutine repl_loop()
131
+        character(len=MAX_LINE_LENGTH) :: input
132
+        type(variable_t), pointer :: variables => null()
133
+        logical :: continue_loop
134
+        integer :: ios
135
+        
136
+        call print_banner()
137
+        continue_loop = .true.
138
+        
139
+        do while (continue_loop)
140
+            write(*, '(A)', advance='no') 'fortbite> '
141
+            read(*, '(A)', iostat=ios) input
142
+            
143
+            if (ios /= 0) then
144
+                ! Handle end of file (Ctrl+D)
145
+                write(*, *)
146
+                write(*, '(A)') 'Goodbye!'
147
+                exit
148
+            end if
149
+            
150
+            ! Skip empty lines
151
+            if (len_trim(input) == 0) cycle
152
+            
153
+            if (is_command(input)) then
154
+                continue_loop = parse_command(input, variables)
155
+            else
156
+                ! Handle mathematical expression (placeholder for now)
157
+                write(*, '(A)') 'Mathematical expression parsing not yet implemented.'
158
+                write(*, '(A,A,A)') 'You entered: "', trim(input), '"'
159
+            end if
160
+        end do
161
+        
162
+        ! Clean up variables
163
+        call cleanup_variables(variables)
164
+    end subroutine repl_loop
165
+    
166
+    !> Convert string to lowercase
167
+    subroutine to_lowercase(str)
168
+        character(len=*), intent(inout) :: str
169
+        integer :: i
170
+        
171
+        do i = 1, len(str)
172
+            if (str(i:i) >= 'A' .and. str(i:i) <= 'Z') then
173
+                str(i:i) = achar(iachar(str(i:i)) + 32)
174
+            end if
175
+        end do
176
+    end subroutine to_lowercase
177
+    
178
+    !> Clear the screen (ANSI escape codes)
179
+    subroutine clear_screen()
180
+        write(*, '(A)') achar(27) // '[2J' // achar(27) // '[H'
181
+    end subroutine clear_screen
182
+    
183
+    !> Handle precision command
184
+    subroutine handle_precision_command(arg)
185
+        character(len=*), intent(in) :: arg
186
+        type(precision_info_t) :: info
187
+        integer :: precision_digits, ios
188
+        
189
+        if (len_trim(arg) == 0) then
190
+            ! Show current precision
191
+            info = get_precision_info(real64)
192
+            write(*, '(A,A)') 'Current precision: ', trim(info%name)
193
+            write(*, '(A,I0)') 'Decimal digits: ', info%decimal_digits
194
+            write(*, '(A,I0)') 'Exponent range: ±', info%exponent_range
195
+        else
196
+            ! Set new precision
197
+            read(arg, *, iostat=ios) precision_digits
198
+            if (ios == 0 .and. precision_digits > 0) then
199
+                write(*, '(A,I0,A)') 'Setting precision to ', precision_digits, ' decimal digits...'
200
+                write(*, '(A)') '(Note: Precision changes will be implemented in Phase 2)'
201
+            else
202
+                write(*, '(A)') 'Invalid precision specification. Use: precision <digits>'
203
+            end if
204
+        end if
205
+    end subroutine handle_precision_command
206
+    
207
+    !> Show system information
208
+    subroutine show_system_info()
209
+        type(precision_info_t) :: info
210
+        
211
+        write(*, '(A)') 'FORTBITE System Information:'
212
+        write(*, '(A)') '  Version: 1.0.0'
213
+        write(*, '(A)') '  Language: Modern Fortran'
214
+        write(*, '(A)') ''
215
+        
216
+        write(*, '(A)') 'Available Precisions:'
217
+        
218
+        info = get_precision_info(real32)
219
+        write(*, '(A,I0,A)') '  Single:   ', precision(1.0_real32), ' digits'
220
+        
221
+        info = get_precision_info(real64)
222
+        write(*, '(A,I0,A)') '  Double:   ', precision(1.0_real64), ' digits'
223
+        
224
+        ! Only show quad if available
225
+        if (real128 > 0) then
226
+            info = get_precision_info(real128)
227
+            write(*, '(A,I0,A)') '  Quad:     ', precision(1.0_real128), ' digits'
228
+        end if
229
+        
230
+        write(*, '(A)') ''
231
+    end subroutine show_system_info
232
+    
233
+    !> Show current variables
234
+    subroutine show_variables(variables)
235
+        type(variable_t), pointer, intent(in) :: variables
236
+        type(variable_t), pointer :: current
237
+        
238
+        current => variables
239
+        
240
+        if (.not. associated(current)) then
241
+            write(*, '(A)') 'No variables defined.'
242
+            return
243
+        end if
244
+        
245
+        write(*, '(A)') 'Current variables:'
246
+        do while (associated(current))
247
+            write(*, '(A,A,A)', advance='no') '  ', current%name, ' = '
248
+            call print_value(current%value)
249
+            current => current%next
250
+        end do
251
+    end subroutine show_variables
252
+    
253
+    !> Clean up variable linked list
254
+    subroutine cleanup_variables(variables)
255
+        type(variable_t), pointer, intent(inout) :: variables
256
+        type(variable_t), pointer :: current, next
257
+        
258
+        current => variables
259
+        do while (associated(current))
260
+            next => current%next
261
+            deallocate(current)
262
+            current => next
263
+        end do
264
+        nullify(variables)
265
+    end subroutine cleanup_variables
266
+    
267
+end module fortbite_io_m
src/fortbite_precision_m.f90added
@@ -0,0 +1,116 @@
1
+!> Precision management module for FORTBITE
2
+!> 
3
+!> This module provides precision control using Fortran's selected_real_kind
4
+!> system, allowing arbitrary precision arithmetic with user control.
5
+module fortbite_precision_m
6
+    use iso_fortran_env, only: int32, int64, real32, real64, real128
7
+    implicit none
8
+    private
9
+    
10
+    ! Public precision parameters
11
+    public :: wp, dp, qp, sp
12
+    public :: default_precision, max_precision
13
+    public :: set_default_precision, get_precision_kind
14
+    public :: precision_info_t, get_precision_info
15
+    
16
+    ! Standard precision kinds
17
+    integer, parameter :: sp = real32                    ! Single precision
18
+    integer, parameter :: dp = real64                    ! Double precision  
19
+    integer, parameter :: qp = real128                   ! Quad precision (if available)
20
+    
21
+    ! Default working precision (can be changed by user)
22
+    integer, parameter :: default_precision = dp
23
+    integer :: wp = default_precision                    ! Working precision
24
+    
25
+    ! Maximum available precision on this system
26
+    integer, parameter :: max_precision = selected_real_kind(33, 4931)
27
+    
28
+    !> Precision information type
29
+    type :: precision_info_t
30
+        integer :: kind_param          !< Kind parameter
31
+        integer :: decimal_digits      !< Decimal precision
32
+        integer :: exponent_range      !< Exponent range
33
+        character(len=20) :: name      !< Human-readable name
34
+        logical :: available           !< Available on this system
35
+    end type precision_info_t
36
+    
37
+contains
38
+
39
+    !> Set the default working precision
40
+    subroutine set_default_precision(precision_digits)
41
+        integer, intent(in) :: precision_digits
42
+        
43
+        integer :: new_kind
44
+        
45
+        ! Get the appropriate kind for requested precision
46
+        new_kind = selected_real_kind(precision_digits)
47
+        
48
+        if (new_kind > 0) then
49
+            wp = new_kind
50
+        else
51
+            write(*, '(A,I0,A)') 'Warning: Precision with ', precision_digits, &
52
+                ' digits not available. Using maximum available precision.'
53
+            wp = max_precision
54
+        end if
55
+    end subroutine set_default_precision
56
+    
57
+    !> Get kind parameter for specified decimal precision
58
+    function get_precision_kind(decimal_digits, exponent_range) result(kind_param)
59
+        integer, intent(in) :: decimal_digits
60
+        integer, intent(in), optional :: exponent_range
61
+        integer :: kind_param
62
+        
63
+        integer :: exp_range
64
+        
65
+        exp_range = 37  ! Default exponent range
66
+        if (present(exponent_range)) exp_range = exponent_range
67
+        
68
+        kind_param = selected_real_kind(decimal_digits, exp_range)
69
+        
70
+        ! Fall back to maximum precision if requested precision unavailable
71
+        if (kind_param < 0) then
72
+            kind_param = max_precision
73
+        end if
74
+    end function get_precision_kind
75
+    
76
+    !> Get information about a precision kind
77
+    function get_precision_info(kind_param) result(info)
78
+        integer, intent(in) :: kind_param
79
+        type(precision_info_t) :: info
80
+        
81
+        info%kind_param = kind_param
82
+        select case (kind_param)
83
+        case (real32)
84
+            info%decimal_digits = precision(1.0_real32)
85
+            info%exponent_range = range(1.0_real32)
86
+        case (real64) 
87
+            info%decimal_digits = precision(1.0_real64)
88
+            info%exponent_range = range(1.0_real64)
89
+        case (real128)
90
+            info%decimal_digits = precision(1.0_real128)
91
+            info%exponent_range = range(1.0_real128)
92
+        case default
93
+            ! For unknown kinds, try to get info using the kind parameter
94
+            info%decimal_digits = 15  ! reasonable default
95
+            info%exponent_range = 307  ! reasonable default
96
+        end select
97
+        info%available = (kind_param > 0)
98
+        
99
+        ! Set human-readable name
100
+        select case (kind_param)
101
+        case (real32)
102
+            info%name = 'Single Precision'
103
+        case (real64)
104
+            info%name = 'Double Precision'
105
+        case (real128)
106
+            info%name = 'Quad Precision'
107
+        case default
108
+            if (kind_param == max_precision) then
109
+                info%name = 'Maximum Precision'
110
+            else
111
+                info%name = 'Custom Precision'
112
+            end if
113
+        end select
114
+    end function get_precision_info
115
+    
116
+end module fortbite_precision_m
src/fortbite_types_m.f90added
@@ -0,0 +1,293 @@
1
+!> Core data types module for FORTBITE
2
+!>
3
+!> Defines the fundamental data types used throughout FORTBITE:
4
+!> scalars, complex numbers, matrices, and variables.
5
+module fortbite_types_m
6
+    use fortbite_precision_m, only: dp, sp, qp
7
+    use iso_fortran_env, only: real64
8
+    use iso_fortran_env, only: int32, int64
9
+    implicit none
10
+    private
11
+    
12
+    ! Public types
13
+    public :: value_t, variable_t, token_t
14
+    public :: value_type_enum, token_type_enum
15
+    public :: VALUE_UNDEFINED, VALUE_SCALAR, VALUE_COMPLEX, VALUE_MATRIX, VALUE_UNIT
16
+    public :: TOKEN_EOF, TOKEN_NUMBER, TOKEN_IDENTIFIER, TOKEN_OPERATOR
17
+    public :: TOKEN_LPAREN, TOKEN_RPAREN, TOKEN_LBRACKET, TOKEN_RBRACKET
18
+    public :: TOKEN_SEMICOLON, TOKEN_COMMA, TOKEN_ASSIGN, TOKEN_PRECISION
19
+    public :: assignment(=)
20
+    
21
+    ! Public procedures
22
+    public :: create_scalar, create_complex, create_matrix
23
+    public :: destroy_value, copy_value, print_value
24
+    public :: is_zero, is_real, get_real_part, get_imag_part
25
+    
26
+    !> Enumeration for value types
27
+    enum, bind(c)
28
+        enumerator :: VALUE_UNDEFINED = 0
29
+        enumerator :: VALUE_SCALAR = 1
30
+        enumerator :: VALUE_COMPLEX = 2  
31
+        enumerator :: VALUE_MATRIX = 3
32
+        enumerator :: VALUE_UNIT = 4
33
+    end enum
34
+    integer, parameter :: value_type_enum = kind(VALUE_UNDEFINED)
35
+    
36
+    !> Enumeration for token types
37
+    enum, bind(c)
38
+        enumerator :: TOKEN_EOF = 0
39
+        enumerator :: TOKEN_NUMBER = 1
40
+        enumerator :: TOKEN_IDENTIFIER = 2
41
+        enumerator :: TOKEN_OPERATOR = 3
42
+        enumerator :: TOKEN_LPAREN = 4
43
+        enumerator :: TOKEN_RPAREN = 5
44
+        enumerator :: TOKEN_LBRACKET = 6
45
+        enumerator :: TOKEN_RBRACKET = 7
46
+        enumerator :: TOKEN_SEMICOLON = 8
47
+        enumerator :: TOKEN_COMMA = 9
48
+        enumerator :: TOKEN_ASSIGN = 10
49
+        enumerator :: TOKEN_PRECISION = 11
50
+    end enum
51
+    integer, parameter :: token_type_enum = kind(TOKEN_EOF)
52
+    
53
+    !> Core value type - can represent scalars, complex numbers, matrices
54
+    type :: value_t
55
+        integer(value_type_enum) :: value_type = VALUE_UNDEFINED
56
+        integer :: precision_kind = real64
57
+        
58
+        ! Union-like storage for different value types
59
+        real(real64) :: scalar_val = 0.0_real64
60
+        complex(real64) :: complex_val = (0.0_real64, 0.0_real64)
61
+        real(real64), allocatable :: matrix_val(:,:)
62
+        complex(real64), allocatable :: complex_matrix_val(:,:)
63
+        
64
+        ! Matrix dimensions
65
+        integer :: rows = 0
66
+        integer :: cols = 0
67
+        logical :: is_complex_matrix = .false.
68
+    end type value_t
69
+    
70
+    !> Variable storage type
71
+    type :: variable_t
72
+        character(len=:), allocatable :: name
73
+        type(value_t) :: value
74
+        type(variable_t), pointer :: next => null()
75
+    end type variable_t
76
+    
77
+    !> Token for lexical analysis
78
+    type :: token_t
79
+        integer(token_type_enum) :: token_type = TOKEN_EOF
80
+        character(len=:), allocatable :: text
81
+        integer :: position = 0
82
+    end type token_t
83
+    
84
+    ! Generic interface for assignment
85
+    interface assignment(=)
86
+        module procedure assign_value
87
+    end interface
88
+    
89
+contains
90
+
91
+    !> Create a scalar value
92
+    function create_scalar(val, precision_kind) result(value)
93
+        real(real64), intent(in) :: val
94
+        integer, intent(in), optional :: precision_kind
95
+        type(value_t) :: value
96
+        
97
+        value%value_type = VALUE_SCALAR
98
+        value%precision_kind = real64
99
+        if (present(precision_kind)) value%precision_kind = precision_kind
100
+        value%scalar_val = val
101
+    end function create_scalar
102
+    
103
+    !> Create a complex value
104
+    function create_complex(real_part, imag_part, precision_kind) result(value)
105
+        real(real64), intent(in) :: real_part, imag_part
106
+        integer, intent(in), optional :: precision_kind
107
+        type(value_t) :: value
108
+        
109
+        value%value_type = VALUE_COMPLEX
110
+        value%precision_kind = real64
111
+        if (present(precision_kind)) value%precision_kind = precision_kind
112
+        value%complex_val = cmplx(real_part, imag_part, kind=real64)
113
+    end function create_complex
114
+    
115
+    !> Create a matrix value
116
+    function create_matrix(matrix_data, precision_kind) result(value)
117
+        real(real64), intent(in) :: matrix_data(:,:)
118
+        integer, intent(in), optional :: precision_kind
119
+        type(value_t) :: value
120
+        
121
+        value%value_type = VALUE_MATRIX
122
+        value%precision_kind = real64
123
+        if (present(precision_kind)) value%precision_kind = precision_kind
124
+        
125
+        value%rows = size(matrix_data, 1)
126
+        value%cols = size(matrix_data, 2)
127
+        value%is_complex_matrix = .false.
128
+        
129
+        allocate(value%matrix_val(value%rows, value%cols))
130
+        value%matrix_val = matrix_data
131
+    end function create_matrix
132
+    
133
+    !> Destroy/deallocate a value
134
+    subroutine destroy_value(value)
135
+        type(value_t), intent(inout) :: value
136
+        
137
+        if (allocated(value%matrix_val)) deallocate(value%matrix_val)
138
+        if (allocated(value%complex_matrix_val)) deallocate(value%complex_matrix_val)
139
+        
140
+        value%value_type = VALUE_UNDEFINED
141
+        value%rows = 0
142
+        value%cols = 0
143
+    end subroutine destroy_value
144
+    
145
+    !> Copy a value (deep copy)
146
+    function copy_value(source) result(dest)
147
+        type(value_t), intent(in) :: source
148
+        type(value_t) :: dest
149
+        
150
+        dest%value_type = source%value_type
151
+        dest%precision_kind = source%precision_kind
152
+        dest%rows = source%rows
153
+        dest%cols = source%cols
154
+        dest%is_complex_matrix = source%is_complex_matrix
155
+        
156
+        select case (source%value_type)
157
+        case (VALUE_SCALAR)
158
+            dest%scalar_val = source%scalar_val
159
+        case (VALUE_COMPLEX)
160
+            dest%complex_val = source%complex_val
161
+        case (VALUE_MATRIX)
162
+            if (allocated(source%matrix_val)) then
163
+                allocate(dest%matrix_val(dest%rows, dest%cols))
164
+                dest%matrix_val = source%matrix_val
165
+            end if
166
+            if (allocated(source%complex_matrix_val)) then
167
+                allocate(dest%complex_matrix_val(dest%rows, dest%cols))
168
+                dest%complex_matrix_val = source%complex_matrix_val
169
+            end if
170
+        end select
171
+    end function copy_value
172
+    
173
+    !> Print a value to standard output
174
+    subroutine print_value(value)
175
+        type(value_t), intent(in) :: value
176
+        
177
+        select case (value%value_type)
178
+        case (VALUE_SCALAR)
179
+            write(*, '(G0)') value%scalar_val
180
+        case (VALUE_COMPLEX)
181
+            if (aimag(value%complex_val) >= 0.0_real64) then
182
+                write(*, '(G0,"+",G0,"i")') real(value%complex_val), aimag(value%complex_val)
183
+            else
184
+                write(*, '(G0,G0,"i")') real(value%complex_val), aimag(value%complex_val)
185
+            end if
186
+        case (VALUE_MATRIX)
187
+            call print_matrix(value)
188
+        case default
189
+            write(*, '(A)') 'Undefined value'
190
+        end select
191
+    end subroutine print_value
192
+    
193
+    !> Print a matrix value
194
+    subroutine print_matrix(value)
195
+        type(value_t), intent(in) :: value
196
+        integer :: i, j
197
+        
198
+        write(*, '(A,I0,"x",I0,A)') '[', value%rows, value%cols, ' matrix]'
199
+        
200
+        if (value%rows <= 10 .and. value%cols <= 10) then
201
+            do i = 1, value%rows
202
+                write(*, '(A)', advance='no') '  '
203
+                do j = 1, value%cols
204
+                    if (value%is_complex_matrix) then
205
+                        write(*, '(SP,G0,G0,"i")', advance='no') &
206
+                            real(value%complex_matrix_val(i,j)), &
207
+                            aimag(value%complex_matrix_val(i,j))
208
+                    else
209
+                        write(*, '(G0)', advance='no') value%matrix_val(i,j)
210
+                    end if
211
+                    if (j < value%cols) write(*, '(A)', advance='no') '  '
212
+                end do
213
+                write(*, *)  ! New line
214
+            end do
215
+        end if
216
+    end subroutine print_matrix
217
+    
218
+    !> Check if a value is zero
219
+    logical function is_zero(value)
220
+        type(value_t), intent(in) :: value
221
+        
222
+        select case (value%value_type)
223
+        case (VALUE_SCALAR)
224
+            is_zero = (abs(value%scalar_val) < epsilon(value%scalar_val))
225
+        case (VALUE_COMPLEX)
226
+            is_zero = (abs(value%complex_val) < epsilon(real(value%complex_val)))
227
+        case default
228
+            is_zero = .false.
229
+        end select
230
+    end function is_zero
231
+    
232
+    !> Check if a value is purely real
233
+    logical function is_real(value)
234
+        type(value_t), intent(in) :: value
235
+        
236
+        select case (value%value_type)
237
+        case (VALUE_SCALAR)
238
+            is_real = .true.
239
+        case (VALUE_COMPLEX)
240
+            is_real = (abs(aimag(value%complex_val)) < epsilon(real(value%complex_val)))
241
+        case default
242
+            is_real = .false.
243
+        end select
244
+    end function is_real
245
+    
246
+    !> Get real part of a value
247
+    function get_real_part(value) result(real_val)
248
+        type(value_t), intent(in) :: value
249
+        real(real64) :: real_val
250
+        
251
+        select case (value%value_type)
252
+        case (VALUE_SCALAR)
253
+            real_val = value%scalar_val
254
+        case (VALUE_COMPLEX)
255
+            real_val = real(value%complex_val)
256
+        case default
257
+            real_val = 0.0_real64
258
+        end select
259
+    end function get_real_part
260
+    
261
+    !> Get imaginary part of a value
262
+    function get_imag_part(value) result(imag_val)
263
+        type(value_t), intent(in) :: value
264
+        real(real64) :: imag_val
265
+        
266
+        select case (value%value_type)
267
+        case (VALUE_SCALAR)
268
+            imag_val = 0.0_real64
269
+        case (VALUE_COMPLEX)
270
+            imag_val = aimag(value%complex_val)
271
+        case default
272
+            imag_val = 0.0_real64
273
+        end select
274
+    end function get_imag_part
275
+    
276
+    !> Assignment operator for values
277
+    subroutine assign_value(lhs, rhs)
278
+        type(value_t), intent(out) :: lhs
279
+        type(value_t), intent(in) :: rhs
280
+        
281
+        ! Simple assignment - let Fortran handle the copying
282
+        lhs%value_type = rhs%value_type
283
+        lhs%precision_kind = rhs%precision_kind
284
+        lhs%scalar_val = rhs%scalar_val
285
+        lhs%complex_val = rhs%complex_val
286
+        lhs%rows = rhs%rows
287
+        lhs%cols = rhs%cols
288
+        lhs%is_complex_matrix = rhs%is_complex_matrix
289
+        
290
+        ! For now, we'll handle matrix copying manually when needed
291
+    end subroutine assign_value
292
+    
293
+end module fortbite_types_m
src/math/arithmetic.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/math/complex.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/math/functions.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/math/matrix.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/math/precision.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/parser/ast.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/parser/lexer.cdeleted
@@ -1,258 +0,0 @@
1
-#include "fortbite.h"
2
-#include <ctype.h>
3
-#include <string.h>
4
-
5
-typedef struct {
6
-    const char* input;
7
-    size_t position;
8
-    size_t length;
9
-    char current_char;
10
-} fortbite_lexer_t;
11
-
12
-static void lexer_advance(fortbite_lexer_t* lexer) {
13
-    if (lexer->position < lexer->length) {
14
-        lexer->position++;
15
-        lexer->current_char = (lexer->position < lexer->length) 
16
-            ? lexer->input[lexer->position] 
17
-            : '\0';
18
-    }
19
-}
20
-
21
-static void lexer_skip_whitespace(fortbite_lexer_t* lexer) {
22
-    while (lexer->current_char != '\0' && isspace(lexer->current_char)) {
23
-        lexer_advance(lexer);
24
-    }
25
-}
26
-
27
-static fortbite_token_t lexer_number(fortbite_lexer_t* lexer) {
28
-    fortbite_token_t token;
29
-    size_t start = lexer->position;
30
-    bool has_dot = false;
31
-    bool has_exp = false;
32
-    
33
-    while (lexer->current_char != '\0' && 
34
-           (isdigit(lexer->current_char) || 
35
-            lexer->current_char == '.' ||
36
-            lexer->current_char == 'e' ||
37
-            lexer->current_char == 'E' ||
38
-            lexer->current_char == '+' ||
39
-            lexer->current_char == '-')) {
40
-        
41
-        if (lexer->current_char == '.') {
42
-            if (has_dot || has_exp) break;
43
-            has_dot = true;
44
-        } else if (lexer->current_char == 'e' || lexer->current_char == 'E') {
45
-            if (has_exp) break;
46
-            has_exp = true;
47
-            lexer_advance(lexer);
48
-            if (lexer->current_char == '+' || lexer->current_char == '-') {
49
-                lexer_advance(lexer);
50
-            }
51
-            continue;
52
-        } else if (lexer->current_char == '+' || lexer->current_char == '-') {
53
-            if (!has_exp) break;
54
-        }
55
-        
56
-        lexer_advance(lexer);
57
-    }
58
-    
59
-    size_t length = lexer->position - start;
60
-    token.type = TOKEN_NUMBER;
61
-    token.value = fortbite_malloc(length + 1);
62
-    strncpy(token.value, &lexer->input[start], length);
63
-    token.value[length] = '\0';
64
-    token.length = length;
65
-    token.position = start;
66
-    
67
-    return token;
68
-}
69
-
70
-static fortbite_token_t lexer_identifier(fortbite_lexer_t* lexer) {
71
-    fortbite_token_t token;
72
-    size_t start = lexer->position;
73
-    
74
-    while (lexer->current_char != '\0' && 
75
-           (isalnum(lexer->current_char) || lexer->current_char == '_')) {
76
-        lexer_advance(lexer);
77
-    }
78
-    
79
-    size_t length = lexer->position - start;
80
-    token.type = TOKEN_IDENTIFIER;
81
-    token.value = fortbite_malloc(length + 1);
82
-    strncpy(token.value, &lexer->input[start], length);
83
-    token.value[length] = '\0';
84
-    token.length = length;
85
-    token.position = start;
86
-    
87
-    return token;
88
-}
89
-
90
-static fortbite_token_t lexer_operator(fortbite_lexer_t* lexer) {
91
-    fortbite_token_t token;
92
-    size_t start = lexer->position;
93
-    
94
-    switch (lexer->current_char) {
95
-        case '+':
96
-        case '-':
97
-        case '*':
98
-        case '/':
99
-        case '^':
100
-        case '%':
101
-            lexer_advance(lexer);
102
-            break;
103
-        case ':':
104
-            lexer_advance(lexer);
105
-            if (lexer->current_char == '=') {
106
-                lexer_advance(lexer);
107
-                token.type = TOKEN_ASSIGN;
108
-            } else if (lexer->current_char == ':') {
109
-                lexer_advance(lexer);
110
-                token.type = TOKEN_PRECISION;
111
-            } else {
112
-                token.type = TOKEN_ERROR;
113
-            }
114
-            break;
115
-        case '=':
116
-            lexer_advance(lexer);
117
-            if (lexer->current_char == '=') {
118
-                lexer_advance(lexer);
119
-            }
120
-            break;
121
-        case '<':
122
-        case '>':
123
-        case '!':
124
-            lexer_advance(lexer);
125
-            if (lexer->current_char == '=') {
126
-                lexer_advance(lexer);
127
-            }
128
-            break;
129
-        default:
130
-            token.type = TOKEN_ERROR;
131
-            lexer_advance(lexer);
132
-            break;
133
-    }
134
-    
135
-    if (token.type != TOKEN_ASSIGN && token.type != TOKEN_PRECISION && token.type != TOKEN_ERROR) {
136
-        token.type = TOKEN_OPERATOR;
137
-    }
138
-    
139
-    size_t length = lexer->position - start;
140
-    token.value = fortbite_malloc(length + 1);
141
-    strncpy(token.value, &lexer->input[start], length);
142
-    token.value[length] = '\0';
143
-    token.length = length;
144
-    token.position = start;
145
-    
146
-    return token;
147
-}
148
-
149
-static fortbite_token_t lexer_next_token(fortbite_lexer_t* lexer) {
150
-    fortbite_token_t token;
151
-    
152
-    lexer_skip_whitespace(lexer);
153
-    
154
-    if (lexer->current_char == '\0') {
155
-        token.type = TOKEN_EOF;
156
-        token.value = NULL;
157
-        token.length = 0;
158
-        token.position = lexer->position;
159
-        return token;
160
-    }
161
-    
162
-    if (isdigit(lexer->current_char)) {
163
-        return lexer_number(lexer);
164
-    }
165
-    
166
-    if (isalpha(lexer->current_char) || lexer->current_char == '_') {
167
-        return lexer_identifier(lexer);
168
-    }
169
-    
170
-    token.position = lexer->position;
171
-    
172
-    switch (lexer->current_char) {
173
-        case '(':
174
-            token.type = TOKEN_LPAREN;
175
-            lexer_advance(lexer);
176
-            break;
177
-        case ')':
178
-            token.type = TOKEN_RPAREN;
179
-            lexer_advance(lexer);
180
-            break;
181
-        case '[':
182
-            token.type = TOKEN_LBRACKET;
183
-            lexer_advance(lexer);
184
-            break;
185
-        case ']':
186
-            token.type = TOKEN_RBRACKET;
187
-            lexer_advance(lexer);
188
-            break;
189
-        case ';':
190
-            token.type = TOKEN_SEMICOLON;
191
-            lexer_advance(lexer);
192
-            break;
193
-        case ',':
194
-            token.type = TOKEN_COMMA;
195
-            lexer_advance(lexer);
196
-            break;
197
-        case 'i':
198
-            if (lexer->position + 1 < lexer->length && 
199
-                !isalnum(lexer->input[lexer->position + 1])) {
200
-                token.type = TOKEN_IDENTIFIER;
201
-                lexer_advance(lexer);
202
-            } else {
203
-                return lexer_identifier(lexer);
204
-            }
205
-            break;
206
-        default:
207
-            return lexer_operator(lexer);
208
-    }
209
-    
210
-    if (token.type != TOKEN_IDENTIFIER) {
211
-        token.value = fortbite_malloc(2);
212
-        token.value[0] = lexer->input[token.position];
213
-        token.value[1] = '\0';
214
-        token.length = 1;
215
-    }
216
-    
217
-    return token;
218
-}
219
-
220
-fortbite_token_t* fortbite_tokenize(const char* input) {
221
-    if (!input) return NULL;
222
-    
223
-    fortbite_lexer_t lexer;
224
-    lexer.input = input;
225
-    lexer.position = 0;
226
-    lexer.length = strlen(input);
227
-    lexer.current_char = (lexer.length > 0) ? input[0] : '\0';
228
-    
229
-    size_t token_capacity = 16;
230
-    size_t token_count = 0;
231
-    fortbite_token_t* tokens = fortbite_malloc(token_capacity * sizeof(fortbite_token_t));
232
-    
233
-    fortbite_token_t token;
234
-    do {
235
-        token = lexer_next_token(&lexer);
236
-        
237
-        if (token_count >= token_capacity) {
238
-            token_capacity *= 2;
239
-            tokens = fortbite_realloc(tokens, token_capacity * sizeof(fortbite_token_t));
240
-        }
241
-        
242
-        tokens[token_count++] = token;
243
-    } while (token.type != TOKEN_EOF && token.type != TOKEN_ERROR);
244
-    
245
-    return tokens;
246
-}
247
-
248
-void fortbite_tokens_free(fortbite_token_t* tokens) {
249
-    if (!tokens) return;
250
-    
251
-    for (size_t i = 0; tokens[i].type != TOKEN_EOF; i++) {
252
-        if (tokens[i].value) {
253
-            fortbite_free(tokens[i].value);
254
-        }
255
-    }
256
-    
257
-    fortbite_free(tokens);
258
-}
src/parser/parser.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/parser/syntax.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/plotting/ascii_plot.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/plotting/data.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/plotting/export.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/plugins/api.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/plugins/loader.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/plugins/registry.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/units/converter.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/units/database.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/units/parser.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/utils/debug.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/utils/file.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"
src/utils/string.cdeleted
@@ -1,1 +0,0 @@
1
-#include "fortbite.h"