Skip to content

Commit b04fff7

Browse files
authored
Merge pull request #3 from begoon/malloc-string2
string malloc
2 parents e2d506e + 35443de commit b04fff7

15 files changed

Lines changed: 249 additions & 82 deletions

File tree

.vscode/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,7 @@
5151
}
5252
},
5353
]
54-
}
54+
},
55+
"terminal.integrated.fontSize": 16,
56+
"editor.fontSize": 16
5557
}

easyc.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import child_process from "node:child_process";
66

77
const { execFileSync } = child_process;
88

9-
function indent(str: string, n: number): string {
9+
function indent(str: string, n: number = 1): string {
1010
return str
1111
.split(/\r?\n/)
1212
.map((line) => " ".repeat(n) + line)
@@ -343,7 +343,7 @@ class ArrayType extends Type {
343343
zero(code: string[]): string {
344344
if (!this.dynamic) return "{0}";
345345
const r = this.hi.context().R();
346-
code.push(`void *${r} AUTOFREE = malloc(sizeof(${this.type.c()}) * (${this.sz()}));`);
346+
code.push(`void *${r} AUTOFREE_ARRAY = malloc(sizeof(${this.type.c()}) * (${this.sz()}));`);
347347
return `{ .data = ${r} }`;
348348
}
349349
typedef = (alias: string) => `typedef ${this.c()} ${alias}`;
@@ -714,6 +714,7 @@ class SET extends Statement {
714714
`type mismatch in SET: ${type.constructor.name} !== ${this.expression.type.constructor.name} at ${this.token}`
715715
);
716716
}
717+
717718
const value = this.expression.v(code);
718719
code.push(`${reference} = ${value};`);
719720
}
@@ -858,8 +859,11 @@ class INPUT extends Statement {
858859
const { type, reference } = expand_variable_reference(variable, variable_reference, code);
859860

860861
if (type instanceof StringType) {
861-
code.push(`scanf("%4095s", ${reference}.data);`);
862-
code.push(`${reference}.sz = strlen(${reference}.data);`);
862+
code.push(`{`);
863+
code.push(indent(`char buf[4096];`, 1));
864+
code.push(indent(`scanf("%4095s", buf);`, 1));
865+
code.push(indent(`${reference} = make_string(buf, strlen(buf));`, 1));
866+
code.push(`}`);
863867
} else if (type instanceof IntegerType) code.push(`scanf("%d", &${reference});`);
864868
else if (type instanceof RealType) code.push(`scanf("%lf", &${reference});`);
865869
else throw new GenerateError(`unsupported variable '${variable}' type in INPUT at ${variable.token}`);
@@ -1058,10 +1062,18 @@ function string_compare(left: Expression, right: Expression, operation: string,
10581062
if (operation !== "==" && operation !== "!=") return null;
10591063

10601064
function is_string_type(e: Expression): [boolean, string | null] {
1061-
if (!(e instanceof VariableReference)) return [false, null];
1062-
const variable = find_existing_variable(e);
1063-
const { type, reference } = expand_variable_reference(variable, e, []);
1064-
return [type instanceof StringType, reference];
1065+
if (e instanceof VariableReference) {
1066+
const variable = find_existing_variable(e);
1067+
const { type, reference } = expand_variable_reference(variable, e, []);
1068+
return [type instanceof StringType, reference];
1069+
}
1070+
if (e.type instanceof StringType) return [true, e.v(code)];
1071+
if (e instanceof FunctionCall) {
1072+
const func = e.context().functions[e.name];
1073+
if (!func) throw new GenerateError(`unknown function '${e.name}' at ${e.token}`);
1074+
if (func.type instanceof StringType) return [true, e.v(code)];
1075+
}
1076+
return [false, null];
10651077
}
10661078

10671079
const [left_string, left_reference] = is_string_type(left);
@@ -1070,7 +1082,15 @@ function string_compare(left: Expression, right: Expression, operation: string,
10701082
if (left_string || right_string) {
10711083
const cmp = operation === "!=" ? "!=" : "==";
10721084
const r = left.context().R();
1073-
code.push(`const int ${r} = strcmp(${left_reference}.data, ${right_reference}.data) ${cmp} 0;`);
1085+
const left_sz = `${left_reference}.sz`;
1086+
const right_sz = `${right_reference}.sz`;
1087+
console.log(right_reference);
1088+
code.push(
1089+
`const int ${r} = ` +
1090+
`${left_sz} == ${right_sz} ` +
1091+
`&& ` +
1092+
`memcmp(${left_reference}.data, ${right_reference}.data, ${left_sz}) ${cmp} 0;`
1093+
);
10741094
return r;
10751095
}
10761096
return null;
@@ -1291,6 +1311,8 @@ function expand_variable_reference(variable: Variable, variable_reference: Varia
12911311
let type: Type = variable.type;
12921312
let reference = variable.name;
12931313

1314+
const owner = { name: variable.name, type: variable.type };
1315+
12941316
for (const part of variable_reference.parts) {
12951317
if (part instanceof VariableSubscript) {
12961318
if (type instanceof AliasType) type = type.reference_type;
@@ -1329,7 +1351,7 @@ function expand_variable_reference(variable: Variable, variable_reference: Varia
13291351
throw new GenerateError(`unexpected variable reference part '${part}' at ${variable.token}`);
13301352
}
13311353
}
1332-
return { type, reference };
1354+
return { type, reference, owner };
13331355
}
13341356

13351357
function find_existing_variable(v: VariableReference): Variable {

life.easy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ PROGRAM Life:
118118

119119
CALL evolution;
120120

121-
CALL rt_pause(0.3);
121+
CALL runtime_pause(0.3);
122122

123123
IF i MOD 10 = 0 THEN
124124
CALL glider(40, 10);

runtime.c

Lines changed: 104 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,7 @@ void free(void *ptr);
1515
#define TRUE 1
1616
#define FALSE 0
1717

18-
#define AUTOFREE __attribute__((cleanup(free_array)))
19-
20-
typedef struct
21-
{
22-
void *data;
23-
} ARRAY;
24-
25-
void free_array(void *ptr)
26-
{
27-
ARRAY *array = (ARRAY *)ptr;
28-
void *data = array->data;
29-
if (data)
30-
{
31-
free(data);
32-
array->data = NULL;
33-
}
34-
}
18+
#define AUTOFREE_ARRAY __attribute__((cleanup(free_array)))
3519

3620
static inline void $sleep(double seconds)
3721
{
@@ -49,25 +33,111 @@ typedef struct
4933
{
5034
int sz;
5135
int immutable;
52-
char data[4096];
36+
char *data;
5337
} STR;
5438

5539
typedef struct
5640
{
5741
const STR *filename;
5842
int line;
5943
int character;
60-
} Location;
44+
} L;
45+
46+
typedef struct string_list
47+
{
48+
struct string_list *next;
49+
STR *str;
50+
} string_list;
51+
52+
static string_list *strings = NULL;
53+
54+
void print_string(STR s, const char *prefix)
55+
{
56+
char *buf = alloca(s.sz + 1);
57+
memcpy(buf, s.data, s.sz);
58+
buf[s.sz] = '\0';
59+
printf("%s: '%s'\n", prefix, buf);
60+
}
6161

62-
int FIX(double v) { return (int)v; }
62+
STR make_string(const char *data, int sz)
63+
{
64+
void *ptr = malloc(sz);
65+
if (!ptr)
66+
{
67+
fprintf(stderr, "make_string|data: out of memory\n");
68+
exit(1);
69+
}
70+
STR *str = malloc(sizeof(STR));
71+
if (!str)
72+
{
73+
fprintf(stderr, "make_string|str: out of memory\n");
74+
exit(1);
75+
}
76+
*str = (STR){.sz = sz, .data = ptr, .immutable = 0};
77+
memcpy(str->data, data, sz);
78+
79+
string_list *reference = malloc(sizeof(string_list));
80+
if (!reference)
81+
{
82+
fprintf(stderr, "make_string|list: out of memory\n");
83+
exit(1);
84+
}
85+
reference->str = str;
86+
reference->next = strings;
87+
strings = reference;
88+
return *str;
89+
}
90+
91+
void free_strings()
92+
{
93+
string_list *list = strings;
94+
while (list)
95+
{
96+
string_list *next = list->next;
97+
if (list->str->data && !list->str->immutable)
98+
{
99+
memset(list->str->data, 0, list->str->sz);
100+
free(list->str->data);
101+
list->str->data = NULL;
102+
103+
memset(list->str, 0, sizeof(STR));
104+
free(list->str);
105+
list->str = NULL;
106+
}
107+
free(list);
108+
list = next;
109+
}
110+
strings = NULL;
111+
}
112+
113+
typedef struct
114+
{
115+
void *data;
116+
} ARRAY;
117+
118+
void free_array(void *ptr)
119+
{
120+
ARRAY *array = (ARRAY *)ptr;
121+
if (array->data)
122+
{
123+
free(array->data);
124+
array->data = NULL;
125+
}
126+
}
127+
128+
int FIX(double v)
129+
{
130+
return (int)v;
131+
}
63132
double FLOAT(int v) { return (double)v; }
64133
double FLOOR(double v) { return (double)((int)v); }
65134
int LENGTH(STR s) { return s.sz; }
66135

67136
STR CHARACTER(int c)
68137
{
69-
STR v = {.sz = 1, .data = {c, 0}};
70-
return v;
138+
char cbuf = (char)c;
139+
STR s = make_string(&cbuf, 1);
140+
return s;
71141
}
72142

73143
STR SUBSTR(STR from, int start, int length)
@@ -99,8 +169,7 @@ STR SUBSTR(STR from, int start, int length)
99169
fprintf(stderr, "substr (%s): start + length > size (%d + %d = %d > %d)\n", buf, start, length, start + length, from.sz);
100170
exit(1);
101171
}
102-
STR v = {.sz = length};
103-
memcpy(v.data, from.data + start, length);
172+
STR v = make_string(from.data + start, length);
104173
return v;
105174
}
106175

@@ -132,20 +201,20 @@ STR $concat(const char *fmt, ...)
132201
else if (*fmt == 'S')
133202
{
134203
const STR *arg = va_arg(args, STR *);
135-
n = arg->sz;
204+
n = (int)sizeof(buf) - sz < arg->sz ? (int)sizeof(buf) - sz : arg->sz;
136205
memcpy(buf + sz, arg->data, n);
137206
}
138207
else if (*fmt == 'A')
139208
{
140209
const STR arg = va_arg(args, STR);
141-
n = arg.sz;
210+
n = (int)sizeof(buf) - sz < arg.sz ? (int)sizeof(buf) - sz : arg.sz;
142211
memcpy(buf + sz, arg.data, n);
143212
}
144213
sz += n;
145214
}
146215
va_end(args);
147-
STR v = {.sz = sz};
148-
memcpy(v.data, buf, sz);
216+
217+
STR v = make_string(buf, sz);
149218
return v;
150219
}
151220

@@ -190,7 +259,7 @@ void $output(const char *fmt, ...)
190259
putchar('\n');
191260
}
192261

193-
void rt_pause(double seconds)
262+
void runtime_pause(double seconds)
194263
{
195264
$sleep(seconds);
196265
}
@@ -206,15 +275,16 @@ void $index(int index, int lo, int hi, const STR *filename, int line, int charac
206275

207276
int main_program();
208277

209-
int main()
278+
void $exit()
210279
{
211-
main_program();
212-
return 0;
280+
free_strings();
281+
exit(0);
213282
}
214283

215-
void $exit()
284+
int main()
216285
{
217-
exit(0);
286+
main_program();
287+
$exit();
218288
}
219289

220290
#pragma clang diagnostic ignored "-Wincompatible-library-redeclaration"

tests/array_1000/x/test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ int main_program()
3232
$output("i", b.data[(1000) - (1000)]);
3333
n = 1000;
3434
{
35-
void *$r1 AUTOFREE = malloc(sizeof(double) * (n - n + 1));
35+
void *$r1 AUTOFREE_ARRAY = malloc(sizeof(double) * (n - n + 1));
3636
struct
3737
{
3838
double *data;
3939
} c = { .data = $r1 };
40-
void *$r2 AUTOFREE = malloc(sizeof(struct
40+
void *$r2 AUTOFREE_ARRAY = malloc(sizeof(struct
4141
{
4242
double data[1 - 0 + 1];
4343
}) * (n - n + 1));

tests/array_dynamic/x/test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ int main_program()
1313
{
1414
sz = 1024;
1515
{
16-
void *$r1 AUTOFREE = malloc(sizeof(int) * (sz - 1 + 1));
16+
void *$r1 AUTOFREE_ARRAY = malloc(sizeof(int) * (sz - 1 + 1));
1717
struct
1818
{
1919
int *data;

0 commit comments

Comments
 (0)