all: fixed memleaks; compiler: closures work
This commit is contained in:
@@ -111,6 +111,6 @@ Value display(Value v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
Value numEqual(Value a, Value b) {
|
||||
Value equal(Value a, Value b) {
|
||||
return MakeInt(a.z.value == b.z.value);
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
(define x 1)
|
||||
|
||||
(define inc (lambda (n) (sum n 1)))
|
||||
(define incr 1)
|
||||
(define inc (lambda (n) (sum n incr)))
|
||||
|
||||
(display (inc x))
|
||||
|
7
main.c
7
main.c
@@ -28,8 +28,13 @@ int main(int argc, char** argv) {
|
||||
inp[size] = '\0';
|
||||
|
||||
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;
|
||||
}
|
||||
|
31
src/ast.c
Normal file
31
src/ast.c
Normal 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]);
|
||||
}
|
@@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum tag {
|
||||
PSEUDO,
|
||||
ATOM,
|
||||
@@ -18,4 +22,6 @@ typedef struct sc_ast {
|
||||
struct sc_ast** children;
|
||||
} sc_ast;
|
||||
|
||||
void sc_ast_free(sc_ast*);
|
||||
|
||||
void sc_ast_print(sc_ast*);
|
||||
|
133
src/compiler.c
133
src/compiler.c
@@ -1,8 +1,26 @@
|
||||
#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 {
|
||||
sc_ast* ast;
|
||||
char* name;
|
||||
char** args;
|
||||
int n_args;
|
||||
} sc_global;
|
||||
|
||||
int n_globals = 0;
|
||||
@@ -33,16 +51,83 @@ char* get_prelude() {
|
||||
|
||||
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) {
|
||||
int i;
|
||||
int len = 0;
|
||||
char** body_vars;
|
||||
globals = realloc(globals, ++n_globals*sizeof(sc_global*));
|
||||
sc_global* g = malloc(sizeof(sc_global));
|
||||
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;
|
||||
}
|
||||
|
||||
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]);
|
||||
return NULL;
|
||||
}
|
||||
@@ -56,6 +141,7 @@ char* compile_define(sc_ast* ast) {
|
||||
char* name = ast->children[1]->value;
|
||||
char* res = malloc(strlen(rhs)+strlen(name)+10);
|
||||
sprintf(res, "Value %s = %s", name, rhs);
|
||||
free(rhs);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -72,12 +158,28 @@ char* compile_list(sc_ast* ast) {
|
||||
reslen += strlen(tmp)+2;
|
||||
res = realloc(res, reslen);
|
||||
snprintf(res, reslen, "%s%s", res, tmp);
|
||||
free(tmp);
|
||||
|
||||
for (i = 2; i < ast->n_children; i++) {
|
||||
tmp = compile_expr(ast->children[i]);
|
||||
reslen += strlen(tmp)+2;
|
||||
res = realloc(res, reslen);
|
||||
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);
|
||||
@@ -93,22 +195,26 @@ char* compile_global(sc_global* global) {
|
||||
sprintf(res, "Value %s(", global->name);
|
||||
int reslen = strlen(res)+1;
|
||||
|
||||
sc_ast* args = global->ast->children[1];
|
||||
for (i = 0; i < args->n_children; i++) {
|
||||
for (i = 0; i < global->n_args; i++) {
|
||||
if (i > 0) {
|
||||
reslen += strlen(args->children[i]->value)+8;
|
||||
reslen += strlen(global->args[i])+8;
|
||||
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 {
|
||||
reslen += strlen(args->children[i]->value)+6;
|
||||
reslen += strlen(global->args[i])+6;
|
||||
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;
|
||||
res = realloc(res, reslen);
|
||||
snprintf(res, reslen, "%s) { return %s; }", res, tmp);
|
||||
free(tmp);
|
||||
free(global->name);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -128,6 +234,7 @@ char* compile(sc_ast* ast) {
|
||||
mainlen += strlen(tmp)+1;
|
||||
main = realloc(main, mainlen);
|
||||
snprintf(main, mainlen, "%s;%s", main, tmp);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_globals; i++) {
|
||||
@@ -136,10 +243,14 @@ char* compile(sc_ast* ast) {
|
||||
reslen += strlen(tmp);
|
||||
res = realloc(res, reslen);
|
||||
snprintf(res, reslen, "%s%s", res, tmp);
|
||||
free(globals[i]);
|
||||
free(tmp);
|
||||
}
|
||||
free(globals);
|
||||
|
||||
res = realloc(res, reslen+mainlen+1);
|
||||
snprintf(res, reslen+mainlen+1, "%s%s;}", res, main);
|
||||
free(main);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -160,7 +271,7 @@ char* compile_expr(sc_ast* ast) {
|
||||
sprintf(tmp, "MakeInt(%s)", ast->value);
|
||||
return tmp;
|
||||
case ATOM:
|
||||
return ast->value;
|
||||
return sc_strcpy(ast->value);
|
||||
case STRING:
|
||||
ret = malloc(strlen(ast->value)+3);
|
||||
sprintf(ret, "\"%s\"", ast->value);
|
||||
@@ -169,7 +280,7 @@ char* compile_expr(sc_ast* ast) {
|
||||
return compile_list(ast);
|
||||
case PSEUDO:
|
||||
for (i = 0; i < ast->n_children; i++) {
|
||||
tmp = compile(ast->children[i]);
|
||||
tmp = compile_expr(ast->children[i]);
|
||||
if (!tmp) continue;
|
||||
retlen += strlen(tmp);
|
||||
if (ret) {
|
||||
|
@@ -1,5 +1,3 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ast.h"
|
||||
|
35
src/parser.c
35
src/parser.c
@@ -86,7 +86,7 @@ sc_ast* read_token(char* inp) {
|
||||
return make_atom(inp);
|
||||
}
|
||||
|
||||
parse_state* read_tokens(parse_state* state) {
|
||||
void read_tokens(parse_state* state) {
|
||||
char* token = state->tokens[0];
|
||||
state->tokens++;
|
||||
int n = state->node->n_children++;
|
||||
@@ -100,7 +100,7 @@ parse_state* read_tokens(parse_state* state) {
|
||||
nstate->tokens = state->tokens;
|
||||
|
||||
while (strncmp(nstate->tokens[0], ")", 2)) {
|
||||
nstate = read_tokens(nstate);
|
||||
read_tokens(nstate);
|
||||
}
|
||||
|
||||
state->node->children[n] = nstate->node;
|
||||
@@ -109,8 +109,6 @@ parse_state* read_tokens(parse_state* state) {
|
||||
} else {
|
||||
state->node->children[n] = read_token(token);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
sc_ast* sc_parse(char* input) {
|
||||
@@ -119,27 +117,16 @@ sc_ast* sc_parse(char* input) {
|
||||
state->tokens = tokens;
|
||||
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) {
|
||||
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]);
|
||||
sc_ast* ast = state->node;
|
||||
free(state);
|
||||
return ast;
|
||||
}
|
||||
|
@@ -1,9 +1,6 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
sc_ast* sc_parse(char*);
|
||||
void sc_ast_print(sc_ast*);
|
||||
|
Reference in New Issue
Block a user