commit 2dc0d6830530017506ff961a6a6ad2f3b530cf98
parent 55078ff21d52c4ba961f6a33eae4af60bdd2d05f
Author: Demonstrandum <moi@knutsen.co>
Date: Wed, 24 Jun 2020 17:10:23 +0100
Fix how functions are parsed.
Diffstat:
8 files changed, 164 insertions(+), 16 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,9 +1,9 @@
CC := gcc
OPT := -O3
-WARN := -Wall -Wpedantic -Wextra -Wshadow
+WARN := -Wall -Wpedantic -Wextra -Wshadow -fcompare-debug-second
CFLAGS := $(WARN) $(OPT)
TARGET := crepl
-OBJS := main.o prelude.o parse.o displays.o error.o execute.o
+OBJS := main.o prelude.o error.o parse.o displays.o builtin.o execute.o
LINKS := -lm -lreadline
ifeq ($(PREFIX),)
@@ -36,6 +36,9 @@ parse.o: error.o
displays.o: parse.o
$(CC) -c $(CFLAGS) src/displays.c
+builtin.o:
+ $(CC) -c $(CFLAGS) src/builtin.c
+
execute.o: parse.o error.o
$(CC) -c $(CFLAGS) src/execute.c
diff --git a/src/builtin.c b/src/builtin.c
@@ -0,0 +1,103 @@
+#include "builtin.h"
+
+NumberNode num_to_float(NumberNode num)
+{
+ NumberNode result = num; // Copy.
+
+ switch (num.type) {
+ case INT:
+ result.type = FLOAT;
+ result.value.f = (fsize)num.value.i;
+ break;
+ case FLOAT:
+ break;
+ default: {
+ ERROR_TYPE = EXECUTION_ERROR;
+ strcpy(ERROR_MSG, "Unsupported number type.");
+ }
+ }
+ return result;
+}
+
+NumberNode num_to_int(NumberNode num)
+{
+ NumberNode result = num; // Copy.
+
+ switch (num.type) {
+ case FLOAT:
+ result.type = INT;
+ result.value.i = (ssize)num.value.f;
+ break;
+ case INT:
+ break;
+ default: {
+ ERROR_TYPE = EXECUTION_ERROR;
+ strcpy(ERROR_MSG, "Unsupported number type.");
+ }
+ }
+ return result;
+}
+
+NumberNode *upcast_pair(NumberNode lhs, NumberNode rhs)
+{
+ NumberNode *pair = malloc(2 * sizeof(NumberNode));
+
+ switch (lhs.type) {
+ case FLOAT: {
+ pair[0] = lhs;
+ pair[1] = num_to_float(rhs);
+ break;
+ }
+ case INT: {
+ switch (rhs.type) {
+ case INT: {
+ pair[0] = lhs;
+ pair[1] = rhs;
+ break;
+ }
+ case FLOAT: {
+ pair[0] = num_to_float(lhs);
+ pair[1] = rhs;
+ break;
+ }
+ default:
+ goto error;
+ }
+ break;
+ }
+ error:
+ default: {
+ ERROR_TYPE = EXECUTION_ERROR;
+ strcpy(ERROR_MSG, "Unsupported number type.");
+ return NULL;
+ }
+ }
+ return pair;
+}
+
+NumberNode *num_add(NumberNode lhs, NumberNode rhs)
+{
+ NumberNode *upcasted = upcast_pair(lhs, rhs);
+ if (upcasted == NULL)
+ return NULL;
+
+ NumberNode *result = upcasted + 0;
+
+ switch (result->type) {
+ case FLOAT:
+ result->value.f = upcasted[0].value.f + upcasted[1].value.f;
+ break;
+ case INT:
+ result->value.i = upcasted[0].value.i + upcasted[1].value.i;
+ break;
+ default: {
+ ERROR_TYPE = EXECUTION_ERROR;
+ strcpy(ERROR_MSG, "Unsupported number type.");
+ return NULL;
+ }
+ }
+ result = realloc(result, sizeof(NumberNode));
+ return result;
+}
+
+
diff --git a/src/builtin.h b/src/builtin.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "prelude.h"
+#include "parse.h"
+#include "error.h"
+
+NumberNode num_to_float(NumberNode);
+NumberNode num_to_int(NumberNode);
+NumberNode *upcast_pair(NumberNode, NumberNode);
+NumberNode *num_add(NumberNode, NumberNode);
+
diff --git a/src/displays.c b/src/displays.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "prelude.h"
#include "parse.h"
diff --git a/src/execute.c b/src/execute.c
@@ -1,6 +1,7 @@
#include "execute.h"
#include "error.h"
#include "parse.h"
+#include "builtin.h"
#include "displays.h"
/// Takes in an execution context (ctx) and a
@@ -33,13 +34,9 @@ DataValue *execute(Context *ctx, const ParseNode *stmt)
NumberNode *r_num = type_check("+", RHS, T_NUMBER, rhs);
if (l_num == NULL || r_num == NULL)
return NULL;
- // TODO: Handle more numbers tham just INTs.
- NumberNode *result_num = malloc(sizeof(NumberNode));
- memcpy(result_num, l_num, sizeof(NumberNode));
// Finally, the addition is performed.
- result_num->value.i = l_num->value.i + r_num->value.i;
data->type = T_NUMBER;
- data->value = result_num;
+ data->value = num_add(*l_num, *r_num);
} else if (strcmp(op, "-") == 0) {
} else {
diff --git a/src/main.c b/src/main.c
@@ -3,6 +3,7 @@
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
+#include <wchar.h>
#include <readline/readline.h>
#include <readline/history.h>
@@ -15,10 +16,10 @@
static const char *PROMPT = "::> ";
-void sigint_handle(int _)
+void sigint_handle(int sig)
{
printf("\b\b "); // Obsucre '^C' output.
- printf("\nInterrupted, [Ctrl-D] to stop inputting.\n");
+ printf("\nInterrupted (%d), [Ctrl-D] to stop inputting.\n", sig);
rl_on_new_line();
rl_replace_line("", 0);
rl_redisplay();
@@ -33,9 +34,16 @@ int main(int argc, char **argv)
puts(" (" COMPILER ") (" __DATE__ ")");
puts("Type \"exit\" or [Ctrl-D] (i.e. EOF) to quit.");
+ bool verbose = false;
+ // Parse command line arguments.
+ for (int i = 0; i < argc; ++i) {
+ if (strcmp(argv[i], "-v") == 0)
+ verbose = true;
+ }
+
// Configure readline.
rl_clear_signals();
- rl_bind_key('\t', rl_complete);
+ rl_bind_key('\t', rl_insert);
signal(SIGINT, sigint_handle);
// Create or fetch history file.
@@ -45,12 +53,16 @@ int main(int argc, char **argv)
if ((tmp = getenv("XDG_CACHE_HOME")) != NULL)
strcpy(cache_loc, tmp);
else if ((tmp = getenv("HOME")) != NULL)
- sprintf(cache_loc, "%s/.cache/", tmp);
+ sprintf(cache_loc, "%s/.cache", tmp);
mkdir(cache_loc, 0777);
strcat(cache_loc, "/crepl.history");
read_history(cache_loc);
+ if (verbose) {
+ printf("Reading history from `%s'.\n", cache_loc);
+ }
+
Context *ctx = init_context();
char *response = NULL;
@@ -73,6 +85,11 @@ int main(int argc, char **argv)
continue;
}
+ printf("\033[%luC\033[1A",
+ strlen(PROMPT)
+ + strlen(response));
+ printf(" ≡ %s\n", display_parsetree(tree));
+
DataValue *result = execute(ctx, tree);
if (result == NULL || ERROR_TYPE != NO_ERROR) {
@@ -80,13 +97,10 @@ int main(int argc, char **argv)
continue;
}
- printf("\033[%luC\033[1A", strlen(PROMPT) + strlen(response));
- printf(" ≡ %s\n", display_parsetree(tree));
printf("#=> %s\n", display_datavalue(result));
//free_datavalue(result);
free_parsenode(tree);
- free(response);
} while (true);
write_history(cache_loc);
diff --git a/src/parse.c b/src/parse.c
@@ -5,6 +5,7 @@
#include <string.h>
#include "error.h"
+#include "displays.h"
#include "parse.h"
void free_token(Token *token)
@@ -232,6 +233,8 @@ ParseNode *parse_prefix(const Token *token, char **rest)
node->type = UNARY_NODE;
node->node.unary = *unary;
+ printf("Parsed prefix as: %s\n\n", display_parsetree(node));
+
break;
}
case TT_LPAREN: {
@@ -372,23 +375,39 @@ ParseNode *parse_expr(char **slice, u16 precedence)
ParseNode *left = parse_prefix(token, slice);
+ if (left == NULL)
+ return NULL;
+
Token *token_ahead = peek(slice);
+
if (token_ahead == NULL)
return left;
u16 current_precedence = token_precedence(token_ahead);
u16 previous_precedence = 0;
+ usize count = 0;
while (precedence < current_precedence) {
+ count += 1;
+ if (count > 301) {
+ ERROR_TYPE = PARSE_ERROR;
+ strcpy(ERROR_MSG, "Could not finish parsing expression.");
+ break;
+ }
if (current_precedence != FUNCTION_PRECEDENCE)
token = lex(slice);
+ else
+ token = peek(slice);
+
+ if (token == NULL)
+ break;
left = parse_infix(left, token, slice, previous_precedence);
if (left == NULL || **slice == '\0')
break;
token_ahead = peek(slice);
- if (token == NULL)
+ if (token_ahead == NULL)
break;
previous_precedence = current_precedence;
diff --git a/src/parse.h b/src/parse.h
@@ -60,7 +60,7 @@ static const Operator KNOWN_OPERATORS[] = {
{ ">", 4, LEFT_ASSOC, INFIX },
{ "<", 4, LEFT_ASSOC, INFIX },
{ "=", 2, RIGHT_ASSOC, INFIX },
- { ",", 1, LEFT_ASSOC, INFIX },
+ { ",", 1, RIGHT_ASSOC, INFIX },
};
// Parse tree nodes: