Coverage Report

Created: 2026-02-23 20:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/alexjokela/projects/lattice/src/builtins.c
Line
Count
Source
1
#include "builtins.h"
2
#include "value.h"
3
#include <stdlib.h>
4
#include <string.h>
5
#include <stdio.h>
6
#include <errno.h>
7
#ifndef __EMSCRIPTEN__
8
  #if defined(LATTICE_HAS_EDITLINE)
9
    #include <editline/readline.h>
10
  #elif defined(LATTICE_HAS_READLINE)
11
    #include <readline/readline.h>
12
    #include <readline/history.h>
13
  #else
14
    static char *readline(const char *prompt) {
15
        if (prompt) fputs(prompt, stdout);
16
        fflush(stdout);
17
        char *buf = malloc(4096);
18
        if (!buf) return NULL;
19
        if (!fgets(buf, 4096, stdin)) { free(buf); return NULL; }
20
        size_t len = strlen(buf);
21
        if (len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
22
        return buf;
23
    }
24
    static void add_history(const char *line) { (void)line; }
25
  #endif
26
#endif
27
28
/* ── builtin_input ── */
29
30
0
char *builtin_input(const char *prompt) {
31
#ifdef __EMSCRIPTEN__
32
    (void)prompt;
33
    return NULL;
34
#else
35
0
    char *line = readline(prompt ? prompt : "");
36
0
    if (line == NULL) return NULL;
37
0
    if (line[0] != '\0') add_history(line);
38
0
    return line;
39
0
#endif
40
0
}
41
42
/* ── builtin_read_file ── */
43
44
273
char *builtin_read_file(const char *path) {
45
273
    FILE *f = fopen(path, "r");
46
273
    if (f == NULL) {
47
0
        return NULL;
48
0
    }
49
50
273
    fseek(f, 0, SEEK_END);
51
273
    long len = ftell(f);
52
273
    fseek(f, 0, SEEK_SET);
53
273
    if (len < 0) { fclose(f); return NULL; }
54
55
273
    char *buf = malloc((size_t)len + 1);
56
273
    if (buf == NULL) {
57
0
        fclose(f);
58
0
        return NULL;
59
0
    }
60
61
273
    size_t read = fread(buf, 1, (size_t)len, f);
62
273
    buf[read] = '\0';
63
273
    fclose(f);
64
65
273
    return buf;
66
273
}
67
68
/* ── builtin_write_file ── */
69
70
57
bool builtin_write_file(const char *path, const char *content) {
71
57
    FILE *f = fopen(path, "w");
72
57
    if (f == NULL) {
73
0
        return false;
74
0
    }
75
76
57
    fputs(content, f);
77
57
    fclose(f);
78
79
57
    return true;
80
57
}
81
82
/* ── builtin_typeof_str ── */
83
84
216
const char *builtin_typeof_str(const LatValue *v) {
85
216
    switch (v->type) {
86
72
        case VAL_INT:     return "Int";
87
18
        case VAL_FLOAT:   return "Float";
88
9
        case VAL_BOOL:    return "Bool";
89
51
        case VAL_STR:     return "String";
90
12
        case VAL_ARRAY:   return "Array";
91
0
        case VAL_STRUCT:  return "Struct";
92
0
        case VAL_CLOSURE: return "Closure";
93
3
        case VAL_UNIT:    return "Unit";
94
9
        case VAL_NIL:     return "Nil";
95
0
        case VAL_RANGE:   return "Range";
96
21
        case VAL_MAP:     return "Map";
97
3
        case VAL_CHANNEL: return "Channel";
98
3
        case VAL_ENUM:    return "Enum";
99
6
        case VAL_SET:     return "Set";
100
3
        case VAL_TUPLE:   return "Tuple";
101
3
        case VAL_BUFFER:  return "Buffer";
102
3
        case VAL_REF:     return "Ref";
103
216
    }
104
0
    return "?";
105
216
}
106
107
/* ── builtin_phase_of_str ── */
108
109
177
const char *builtin_phase_of_str(const LatValue *v) {
110
177
    switch (v->phase) {
111
60
        case VTAG_FLUID:      return "fluid";
112
69
        case VTAG_CRYSTAL:    return "crystal";
113
45
        case VTAG_UNPHASED:   return "unphased";
114
3
        case VTAG_SUBLIMATED: return "sublimated";
115
177
    }
116
0
    return "?";
117
177
}
118
119
/* ── builtin_to_string ── */
120
121
531
char *builtin_to_string(const LatValue *v) {
122
531
    return value_display(v);
123
531
}
124
125
/* ── builtin_ord ── */
126
127
12
int64_t builtin_ord(const char *s) {
128
12
    if (s[0] == '\0') {
129
0
        return -1;
130
0
    }
131
12
    return (int64_t)(unsigned char)s[0];
132
12
}
133
134
/* ── builtin_chr ── */
135
136
6
char *builtin_chr(int64_t code) {
137
6
    if (code >= 0 && code <= 127) {
138
6
        char buf[2];
139
6
        buf[0] = (char)code;
140
6
        buf[1] = '\0';
141
6
        return strdup(buf);
142
6
    }
143
0
    return strdup("?");
144
6
}
145
146
/* ── builtin_parse_int ── */
147
148
6
int64_t builtin_parse_int(const char *s, bool *ok) {
149
6
    char *endptr;
150
6
    errno = 0;
151
6
    long long val = strtoll(s, &endptr, 10);
152
6
    if (errno != 0 || endptr == s || *endptr != '\0') {
153
0
        *ok = false;
154
0
        return 0;
155
0
    }
156
6
    *ok = true;
157
6
    return (int64_t)val;
158
6
}
159
160
/* ── builtin_parse_float ── */
161
162
3
double builtin_parse_float(const char *s, bool *ok) {
163
3
    char *endptr;
164
3
    errno = 0;
165
3
    double val = strtod(s, &endptr);
166
3
    if (errno != 0 || endptr == s || *endptr != '\0') {
167
0
        *ok = false;
168
0
        return 0.0;
169
0
    }
170
3
    *ok = true;
171
3
    return val;
172
3
}