all: fixed memleaks; compiler: closures work
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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
7
main.c
@@ -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
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
|
#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*);
|
||||||
|
133
src/compiler.c
133
src/compiler.c
@@ -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) {
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
|
37
src/parser.c
37
src/parser.c
@@ -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]);
|
||||||
const char* tag_to_string(int x) {
|
t++;
|
||||||
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;}
|
|
||||||
}
|
}
|
||||||
}
|
free(tokens);
|
||||||
|
|
||||||
void sc_ast_print(sc_ast* ast) {
|
sc_ast* ast = state->node;
|
||||||
int i;
|
free(state);
|
||||||
|
return ast;
|
||||||
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,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*);
|
|
||||||
|
Reference in New Issue
Block a user