all: fixed memleaks; compiler: closures work

This commit is contained in:
2017-09-07 17:41:27 +02:00
parent a37ec816e6
commit 682bc9db60
9 changed files with 180 additions and 44 deletions

View File

@@ -111,6 +111,6 @@ Value display(Value v) {
return v; return v;
} }
Value numEqual(Value a, Value b) { Value equal(Value a, Value b) {
return MakeInt(a.z.value == b.z.value); return MakeInt(a.z.value == b.z.value);
} }

View File

@@ -1,5 +1,6 @@
(define x 1) (define x 1)
(define inc (lambda (n) (sum n 1))) (define incr 1)
(define inc (lambda (n) (sum n incr)))
(display (inc x)) (display (inc x))

7
main.c
View File

@@ -28,8 +28,13 @@ int main(int argc, char** argv) {
inp[size] = '\0'; inp[size] = '\0';
sc_ast* ast = sc_parse(inp); sc_ast* ast = sc_parse(inp);
char* out = compile(ast);
printf("%s\n", compile(ast)); printf("%s\n", out);
free(inp);
free(out);
sc_ast_free(ast);
return 0; return 0;
} }

31
src/ast.c Normal file
View File

@@ -0,0 +1,31 @@
#include "ast.h"
void sc_ast_free(sc_ast* ast) {
int i;
for (i = 0; i < ast->n_children; ++i) sc_ast_free(ast->children[i]);
free(ast->children);
free(ast->value);
free(ast);
}
const char* tag_to_string(int x) {
switch(x) {
case PSEUDO: return "pseudo";
case ATOM: return "atom";
case STRING: return "string";
case INT: return "int";
case FLOAT: return "float";
case LIST: return "list";
default: {char* t=malloc(3); snprintf(t, 3, "%d", x); return t;}
}
}
void sc_ast_print(sc_ast* ast) {
int i;
printf("%s: %s\n", tag_to_string(ast->tag), ast->value);
for (i = 0; i < ast->n_children; ++i) sc_ast_print(ast->children[i]);
}

View File

@@ -1,4 +1,8 @@
#pragma once #pragma once
#include <stdlib.h>
#include <stdio.h>
enum tag { enum tag {
PSEUDO, PSEUDO,
ATOM, ATOM,
@@ -18,4 +22,6 @@ typedef struct sc_ast {
struct sc_ast** children; struct sc_ast** children;
} sc_ast; } sc_ast;
void sc_ast_free(sc_ast*);
void sc_ast_print(sc_ast*);

View File

@@ -1,8 +1,26 @@
#include "compiler.h" #include "compiler.h"
const char* primitives[5] = {
"sum",
"product",
"difference",
"display",
"equal"
};
int n_primitives = 5;
char* sc_strcpy(char* src) {
char* dst = malloc(strlen(src)+1);
strcpy(dst, src);
return dst;
}
typedef struct sc_global { typedef struct sc_global {
sc_ast* ast; sc_ast* ast;
char* name; char* name;
char** args;
int n_args;
} sc_global; } sc_global;
int n_globals = 0; int n_globals = 0;
@@ -33,16 +51,83 @@ char* get_prelude() {
char* compile_expr(sc_ast* ast); char* compile_expr(sc_ast* ast);
int in_list(char* elem, char** list, int len) {
int i;
for (i = 0; i < len; i++) if (!strcmp(elem, list[i])) return 1;
return 0;
}
char** get_vars(sc_ast* body, char** args, int args_len, int* len) {
int i;
int j;
char** ret = NULL;
int tmplen = 0;
char** tmp;
for (i = 0; i < body->n_children; i++) {
if (body->children[i]->tag == ATOM &&
!in_list(body->children[i]->value, args, args_len) &&
!in_list(body->children[i]->value, (char**)primitives, n_primitives)) {
(*len)++;
ret = realloc(ret, *len*sizeof(char*));
ret[*len-1] = sc_strcpy(body->children[i]->value);
} else if (body->children[i]->tag == LIST) {
tmp = get_vars(body->children[i], args, args_len, &tmplen);
ret = realloc(ret, (*len+tmplen)*sizeof(char*));
for (j = 0; j < tmplen; j++) {
ret[*len+j] = tmp[j];
}
len += tmplen;
tmplen = 0;
free(tmp);
}
}
return ret;
}
sc_global* find_global(char* name) {
int i;
for (i = 0; i < n_globals; i++) {
if (!strcmp(name, globals[i]->name)) return globals[i];
}
return NULL;
}
void add_global(char* name, sc_ast* ast) { void add_global(char* name, sc_ast* ast) {
int i;
int len = 0;
char** body_vars;
globals = realloc(globals, ++n_globals*sizeof(sc_global*)); globals = realloc(globals, ++n_globals*sizeof(sc_global*));
sc_global* g = malloc(sizeof(sc_global)); sc_global* g = malloc(sizeof(sc_global));
g->name = name; g->name = name;
g->ast = ast; g->ast = ast->children[ast->n_children-1];
sc_ast* arg_list = ast->children[1];
g->args = malloc(sizeof(char*)*arg_list->n_children);
for (i = 0; i < arg_list->n_children; i++) {
g->args[i] = sc_strcpy(arg_list->children[i]->value);
}
body_vars = get_vars(g->ast, g->args, arg_list->n_children, &len);
g->args = realloc(g->args, sizeof(char*)*(arg_list->n_children+len));
for (i = 0; i < len; i++) {
g->args[arg_list->n_children+i] = body_vars[i];
}
free(body_vars);
g->n_args = arg_list->n_children+len;
globals[n_globals-1] = g; globals[n_globals-1] = g;
} }
char* compile_lambda(sc_ast* ast) { char* compile_lambda(sc_ast* ast) {
char* name = ast->children[1]->value; char* name = sc_strcpy(ast->children[1]->value);
add_global(name, ast->children[2]); add_global(name, ast->children[2]);
return NULL; return NULL;
} }
@@ -56,6 +141,7 @@ char* compile_define(sc_ast* ast) {
char* name = ast->children[1]->value; char* name = ast->children[1]->value;
char* res = malloc(strlen(rhs)+strlen(name)+10); char* res = malloc(strlen(rhs)+strlen(name)+10);
sprintf(res, "Value %s = %s", name, rhs); sprintf(res, "Value %s = %s", name, rhs);
free(rhs);
return res; return res;
} }
@@ -72,12 +158,28 @@ char* compile_list(sc_ast* ast) {
reslen += strlen(tmp)+2; reslen += strlen(tmp)+2;
res = realloc(res, reslen); res = realloc(res, reslen);
snprintf(res, reslen, "%s%s", res, tmp); snprintf(res, reslen, "%s%s", res, tmp);
free(tmp);
for (i = 2; i < ast->n_children; i++) { for (i = 2; i < ast->n_children; i++) {
tmp = compile_expr(ast->children[i]); tmp = compile_expr(ast->children[i]);
reslen += strlen(tmp)+2; reslen += strlen(tmp)+2;
res = realloc(res, reslen); res = realloc(res, reslen);
snprintf(res, reslen, "%s, %s", res, tmp); snprintf(res, reslen, "%s, %s", res, tmp);
free(tmp);
}
sc_global* g = find_global(ast->children[0]->value);
if (g) {
int start = ast->n_children-1;
int end = g->n_args;
for (i = start; i < end; i++) {
tmp = sc_strcpy(g->args[i]);
reslen += strlen(tmp)+2;
res = realloc(res, reslen);
snprintf(res, reslen, "%s, %s", res, tmp);
free(tmp);
}
} }
res = realloc(res, reslen+1); res = realloc(res, reslen+1);
@@ -93,22 +195,26 @@ char* compile_global(sc_global* global) {
sprintf(res, "Value %s(", global->name); sprintf(res, "Value %s(", global->name);
int reslen = strlen(res)+1; int reslen = strlen(res)+1;
sc_ast* args = global->ast->children[1]; for (i = 0; i < global->n_args; i++) {
for (i = 0; i < args->n_children; i++) {
if (i > 0) { if (i > 0) {
reslen += strlen(args->children[i]->value)+8; reslen += strlen(global->args[i])+8;
res = realloc(res, reslen); res = realloc(res, reslen);
snprintf(res, reslen, "%s, Value %s", res, args->children[i]->value); snprintf(res, reslen, "%s, Value %s", res, global->args[i]);
} else { } else {
reslen += strlen(args->children[i]->value)+6; reslen += strlen(global->args[i])+6;
res = realloc(res, reslen); res = realloc(res, reslen);
snprintf(res, reslen, "%sValue %s", res, args->children[i]->value); snprintf(res, reslen, "%sValue %s", res, global->args[i]);
} }
free(global->args[i]);
} }
tmp = compile_expr(global->ast->children[2]); free(global->args);
tmp = compile_expr(global->ast);
reslen += strlen(tmp)+14; reslen += strlen(tmp)+14;
res = realloc(res, reslen); res = realloc(res, reslen);
snprintf(res, reslen, "%s) { return %s; }", res, tmp); snprintf(res, reslen, "%s) { return %s; }", res, tmp);
free(tmp);
free(global->name);
return res; return res;
} }
@@ -128,6 +234,7 @@ char* compile(sc_ast* ast) {
mainlen += strlen(tmp)+1; mainlen += strlen(tmp)+1;
main = realloc(main, mainlen); main = realloc(main, mainlen);
snprintf(main, mainlen, "%s;%s", main, tmp); snprintf(main, mainlen, "%s;%s", main, tmp);
free(tmp);
} }
for (i = 0; i < n_globals; i++) { for (i = 0; i < n_globals; i++) {
@@ -136,10 +243,14 @@ char* compile(sc_ast* ast) {
reslen += strlen(tmp); reslen += strlen(tmp);
res = realloc(res, reslen); res = realloc(res, reslen);
snprintf(res, reslen, "%s%s", res, tmp); snprintf(res, reslen, "%s%s", res, tmp);
free(globals[i]);
free(tmp);
} }
free(globals);
res = realloc(res, reslen+mainlen+1); res = realloc(res, reslen+mainlen+1);
snprintf(res, reslen+mainlen+1, "%s%s;}", res, main); snprintf(res, reslen+mainlen+1, "%s%s;}", res, main);
free(main);
return res; return res;
} }
@@ -160,7 +271,7 @@ char* compile_expr(sc_ast* ast) {
sprintf(tmp, "MakeInt(%s)", ast->value); sprintf(tmp, "MakeInt(%s)", ast->value);
return tmp; return tmp;
case ATOM: case ATOM:
return ast->value; return sc_strcpy(ast->value);
case STRING: case STRING:
ret = malloc(strlen(ast->value)+3); ret = malloc(strlen(ast->value)+3);
sprintf(ret, "\"%s\"", ast->value); sprintf(ret, "\"%s\"", ast->value);
@@ -169,7 +280,7 @@ char* compile_expr(sc_ast* ast) {
return compile_list(ast); return compile_list(ast);
case PSEUDO: case PSEUDO:
for (i = 0; i < ast->n_children; i++) { for (i = 0; i < ast->n_children; i++) {
tmp = compile(ast->children[i]); tmp = compile_expr(ast->children[i]);
if (!tmp) continue; if (!tmp) continue;
retlen += strlen(tmp); retlen += strlen(tmp);
if (ret) { if (ret) {

View File

@@ -1,5 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "ast.h" #include "ast.h"

View File

@@ -86,7 +86,7 @@ sc_ast* read_token(char* inp) {
return make_atom(inp); return make_atom(inp);
} }
parse_state* read_tokens(parse_state* state) { void read_tokens(parse_state* state) {
char* token = state->tokens[0]; char* token = state->tokens[0];
state->tokens++; state->tokens++;
int n = state->node->n_children++; int n = state->node->n_children++;
@@ -100,7 +100,7 @@ parse_state* read_tokens(parse_state* state) {
nstate->tokens = state->tokens; nstate->tokens = state->tokens;
while (strncmp(nstate->tokens[0], ")", 2)) { while (strncmp(nstate->tokens[0], ")", 2)) {
nstate = read_tokens(nstate); read_tokens(nstate);
} }
state->node->children[n] = nstate->node; state->node->children[n] = nstate->node;
@@ -109,8 +109,6 @@ parse_state* read_tokens(parse_state* state) {
} else { } else {
state->node->children[n] = read_token(token); state->node->children[n] = read_token(token);
} }
return state;
} }
sc_ast* sc_parse(char* input) { sc_ast* sc_parse(char* input) {
@@ -119,27 +117,16 @@ sc_ast* sc_parse(char* input) {
state->tokens = tokens; state->tokens = tokens;
state->node = make_pseudo(); state->node = make_pseudo();
while (state->tokens[0]) state = read_tokens(state); while (state->tokens[0]) read_tokens(state);
return state->node; char** t = tokens;
while(t[0]) {
if (!strcmp(t[0], "(") || !strcmp(t[0], ")")) free(t[0]);
t++;
} }
free(tokens);
const char* tag_to_string(int x) { sc_ast* ast = state->node;
switch(x) { free(state);
case PSEUDO: return "pseudo"; return ast;
case ATOM: return "atom";
case STRING: return "string";
case INT: return "int";
case FLOAT: return "float";
case LIST: return "list";
default: {char* t=malloc(3); snprintf(t, 3, "%d", x); return t;}
}
}
void sc_ast_print(sc_ast* ast) {
int i;
printf("%s: %s\n", tag_to_string(ast->tag), ast->value);
for (i = 0; i < ast->n_children; ++i) sc_ast_print(ast->children[i]);
} }

View File

@@ -1,9 +1,6 @@
#include <ctype.h> #include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "ast.h" #include "ast.h"
sc_ast* sc_parse(char*); sc_ast* sc_parse(char*);
void sc_ast_print(sc_ast*);