Commit f6310763 authored by Chris Müller's avatar Chris Müller
Browse files

Arithmetic runtime operations / Exceptions



Add arithemtic function +,-,/,* to the toplevel runtime environment
Add proper exception handling.
Signed-off-by: Chris Müller's avatarChris Mueller <ruunsmail@gmail.com>
parent e96d8162
......@@ -19,6 +19,14 @@
#include "cherry/runtime.h"
struct org_cherry_value* org_cherry_core_type(struct org_cherry_environment* env, struct org_cherry_value* args);
struct org_cherry_value* org_cherry_core_add(struct org_cherry_environment* env, struct org_cherry_value* args);
struct org_cherry_value* org_cherry_core_sub(struct org_cherry_environment* env, struct org_cherry_value* args);
struct org_cherry_value* org_cherry_core_mul(struct org_cherry_environment* env, struct org_cherry_value* args);
struct org_cherry_value* org_cherry_core_div(struct org_cherry_environment* env, struct org_cherry_value* args);
struct org_cherry_value* org_cherry_primitive_println(struct org_cherry_environment* env, struct org_cherry_value* args);
struct org_cherry_value* org_cherry_primitive_raise(struct org_cherry_environment* env, struct org_cherry_value* args);
......
......@@ -90,6 +90,8 @@ struct org_cherry_value* org_cherry_float(cy_float_t float_value);
struct org_cherry_value* org_cherry_string(const cy_byte_t* string_value);
struct org_cherry_value* org_cherry_char(cy_unicode_t char_value);
struct org_cherry_value* org_cherry_value_dup(struct org_cherry_value* value);
struct org_cherry_pair {
struct org_cherry_meta meta;
......@@ -152,7 +154,7 @@ int org_cherry_env_add(struct org_cherry_environment
struct org_cherry_environment* org_cherry_env_push_exception_point(struct org_cherry_environment* env);
struct org_cherry_environment* org_cherry_env_pop_exception_point(struct org_cherry_environment* env);
void org_cherry_env_raise_exception(struct org_cherry_environment* env, struct org_cherry_value* e);
void org_cherry_env_raise(struct org_cherry_environment* env, struct org_cherry_value* e);
......
......@@ -6,6 +6,7 @@ set(CORE_SOURCES
unicode.c
tables.c
exception.c
primitives/core.c
primitives/print.c
primitives/system.c)
......
......@@ -50,18 +50,29 @@ org_cherry_process_file(const char* filename, const cy_byte_t* method, struct or
struct org_cherry_context* context = org_cherry_context(src, src, CY_SUPRESS_COMMENTS);
struct org_cherry_value* exp = org_cherry_read(context);
while(exp != 0) {
org_cherry_eval(env, exp);
org_cherry_env_push_exception_point(env);
exp = org_cherry_read(context);
}
if(!setjmp(EXCEPTION_JUMP(env))) {
while(exp != 0) {
org_cherry_eval(env, exp);
exp = org_cherry_read(context);
}
if(method) {
struct org_cherry_value* main = org_cherry_list_cons(org_cherry_symbol(method), arguments);
if(method) {
struct org_cherry_value* main = org_cherry_list_cons(org_cherry_symbol(method), arguments);
org_cherry_eval(env, main);
org_cherry_eval(env, main);
}
} else {
fprintf(stderr, "EXCEPTION: ");
org_cherry_print(stderr, HEAD(EXCEPTION_DATA(env)));
fprintf(stderr, "\n");
exit(EXIT_FAILURE);
}
org_cherry_env_pop_exception_point(env);
exit(EXIT_SUCCESS);
}
......@@ -72,6 +83,8 @@ org_cherry_start_repl(void)
printf("Cherry Interpreter 0.1\n\n");
struct org_cherry_environment* env = org_cherry_environment();
org_cherry_env_push_exception_point(env);
while(1) {
cy_byte_t* line = (cy_byte_t*) readline("> ");
......@@ -79,11 +92,19 @@ org_cherry_start_repl(void)
struct org_cherry_context* context = org_cherry_context_repl(line);
struct org_cherry_value* exp = org_cherry_read(context);
org_cherry_print(stdout, org_cherry_eval(env, exp));
printf("\n");
if(!setjmp(EXCEPTION_JUMP(env))) {
org_cherry_print(stdout, org_cherry_eval(env, exp));
printf("\n");
} else {
fprintf(stderr, "EXCEPTION: ");
org_cherry_print(stderr, EXCEPTION_DATA(env));
fprintf(stderr, "\n");
}
free(line);
}
org_cherry_env_pop_exception_point(env);
}
......
......@@ -129,7 +129,8 @@ org_cherry_eval_begin(struct org_cherry_environment* env, struct org_cherry_valu
if(val == 0){
return_val = org_cherry_apply(env, org_cherry_eval(env, HEAD(value)), org_cherry_emptylist);
} else if(!IS_NULL(HEAD(TAIL(value))) && val) {
return_val = org_cherry_apply(env, org_cherry_eval(env, HEAD(TAIL(value))), EXCEPTION_DATA(env));
return_val = org_cherry_apply(env, org_cherry_eval(env, HEAD(TAIL(value))),
org_cherry_list_cons(EXCEPTION_DATA(env), org_cherry_emptylist));
}
if(!IS_NULL(HEAD(TAIL(TAIL(value)))))
......
......@@ -55,7 +55,7 @@ org_cherry_env_pop_exception_point(struct org_cherry_environment* env)
void
org_cherry_env_raise_exception(struct org_cherry_environment* env, struct org_cherry_value* e)
org_cherry_env_raise(struct org_cherry_environment* env, struct org_cherry_value* e)
{
env->exception_stack->data = e;
longjmp(env->exception_stack->jump, 1);
......
/*
* Cherry programming language
* Copyright (C) 2013 Christoph Mueller
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <setjmp.h>
struct org_cherry_exception {
jmp_buf jump;
cy_const_pointer_t data;
};
/*
* Cherry programming language
* Copyright (C) 2013 Christoph Mueller
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "cherry/primitives.h"
struct org_cherry_value*
org_cherry_core_type(struct org_cherry_environment* env, struct org_cherry_value* args)
{
if(IS_NULL(args))
org_cherry_env_raise(env, org_cherry_string("type functions expects an argument"));
switch(HEAD(args)->meta.type) {
case CY_FIXNUM:
return org_cherry_symbol("#fixnum");
case CY_FLOAT:
return org_cherry_symbol("#float");
case CY_BOOLEAN:
return org_cherry_symbol("#boolean");
case CY_CHAR:
return org_cherry_symbol("#char");
case CY_SYMBOL:
return org_cherry_symbol("#symbol");
case CY_STRING:
return org_cherry_symbol("#string");
case CY_PROCEDURE:
return org_cherry_symbol("#procedure");
case CY_PRIMITIVE:
return org_cherry_symbol("#primitive");
case CY_PAIR:
return org_cherry_symbol("#pair");
}
return org_cherry_false;
}
struct org_cherry_value*
org_cherry_core_add(struct org_cherry_environment* env, struct org_cherry_value* args)
{
struct org_cherry_value* v = org_cherry_fixnum(0);
while(!IS_NULL(args)) {
struct org_cherry_value* x = HEAD(args);
switch(x->meta.type) {
case CY_FIXNUM:
if(IS_FIXNUM(v))
v->fixnum_value += x->fixnum_value;
else
v->float_value += x->fixnum_value;
break;
case CY_FLOAT:
if(IS_FIXNUM(v)) {
v->float_value = v->fixnum_value + x->float_value;
v->meta.type = CY_FLOAT;
} else {
v->float_value += x->float_value;
}
break;
default:
org_cherry_env_raise(env, org_cherry_string("Addition performed with a non-numerical datatype"));
}
args = TAIL(args);
}
return v;
}
struct org_cherry_value*
org_cherry_core_sub(struct org_cherry_environment* env, struct org_cherry_value* args)
{
if(IS_NULL(args))
return org_cherry_fixnum(0);
else if(!IS_FIXNUM(HEAD(args)) && !IS_FLOAT(HEAD(args)))
org_cherry_env_raise(env, org_cherry_string("First operand in Subtraction is not a numerical datatype"));
struct org_cherry_value* v = org_cherry_value_dup(HEAD(args));
args = TAIL(args);
org_cherry_print(stdout, v);
printf("\n");
while(!IS_NULL(args)) {
struct org_cherry_value* x = HEAD(args);
switch(x->meta.type) {
case CY_FIXNUM:
if(IS_FIXNUM(v))
v->fixnum_value -= x->fixnum_value;
else
v->float_value -= x->fixnum_value;
break;
case CY_FLOAT:
if(IS_FIXNUM(v)) {
v->float_value = v->fixnum_value - x->float_value;
v->meta.type = CY_FLOAT;
} else {
v->float_value -= x->float_value;
}
break;
default:
org_cherry_env_raise(env, org_cherry_string("Subtraction performed with a non-numerical datatype"));
}
args = TAIL(args);
}
return v;
}
struct org_cherry_value*
org_cherry_core_mul(struct org_cherry_environment* env, struct org_cherry_value* args)
{
struct org_cherry_value* v = org_cherry_fixnum(1);
while(!IS_NULL(args)) {
struct org_cherry_value* x = HEAD(args);
switch(x->meta.type) {
case CY_FIXNUM:
if(IS_FIXNUM(v))
v->fixnum_value *= x->fixnum_value;
else
v->float_value *= x->fixnum_value;
break;
case CY_FLOAT:
if(IS_FIXNUM(v)) {
v->float_value = v->fixnum_value * x->float_value;
v->meta.type = CY_FLOAT;
} else {
v->float_value *= x->float_value;
}
break;
default:
org_cherry_env_raise(env, org_cherry_string("Multiplication performed with a non-numerical datatype"));
}
args = TAIL(args);
}
return v;
}
struct org_cherry_value*
org_cherry_core_div(struct org_cherry_environment* env, struct org_cherry_value* args)
{
if(IS_NULL(args))
return org_cherry_fixnum(0);
else if(!IS_FIXNUM(HEAD(args)) && !IS_FLOAT(HEAD(args)))
org_cherry_env_raise(env, org_cherry_string("First operand in Division is not a numerical datatype"));
struct org_cherry_value* v = org_cherry_value_dup(HEAD(args));
args = TAIL(args);
while(!IS_NULL(args)) {
struct org_cherry_value* x = HEAD(args);
switch(x->meta.type) {
case CY_FIXNUM:
if(x->fixnum_value == 0)
org_cherry_env_raise(env, org_cherry_string("Division by Zero"));
if(IS_FIXNUM(v))
v->fixnum_value /= x->fixnum_value;
else
v->float_value /= x->fixnum_value;
break;
case CY_FLOAT:
if(x->float_value == 0.0)
org_cherry_env_raise(env, org_cherry_string("Division by Zero"));
if(IS_FIXNUM(v)) {
v->float_value = v->fixnum_value / x->float_value;
v->meta.type = CY_FLOAT;
} else {
v->float_value /= x->float_value;
}
break;
default:
org_cherry_env_raise(env, org_cherry_string("Subtraction performed with a non-numerical datatype"));
}
args = TAIL(args);
}
return v;
}
......@@ -29,9 +29,9 @@ struct org_cherry_value*
org_cherry_primitive_raise(struct org_cherry_environment* env, struct org_cherry_value* args)
{
if(IS_NULL(args))
org_cherry_env_raise_exception(env, org_cherry_emptylist);
org_cherry_env_raise(env, org_cherry_emptylist);
else
org_cherry_env_raise_exception(env, args);
org_cherry_env_raise(env, HEAD(args));
return org_cherry_false;
}
......@@ -57,6 +57,18 @@ org_cherry_string_dup(const cy_byte_t* str)
return dest;
}
struct org_cherry_value*
org_cherry_value_dup(struct org_cherry_value* value)
{
struct org_cherry_value* result = GC_MALLOC(sizeof(struct org_cherry_value));
memcpy(result, value, sizeof(struct org_cherry_value));
return result;
}
// ----------------------------------------------------------------------------
// string converter
// ----------------------------------------------------------------------------
......@@ -385,13 +397,16 @@ org_cherry_environment(void)
env->mapping = org_cherry_symbollist();
env->exception_stack = 0;
org_cherry_env_add(env,
org_cherry_symbol("println"),
org_cherry_primitive(org_cherry_primitive_println));
#define proc_to_env(ENV, STR, FUN) \
org_cherry_env_add(ENV, org_cherry_symbol(STR), org_cherry_primitive(FUN))
org_cherry_env_add(env,
org_cherry_symbol("raise"),
org_cherry_primitive(org_cherry_primitive_raise));
proc_to_env(env, "println", org_cherry_primitive_println);
proc_to_env(env, "raise", org_cherry_primitive_raise);
proc_to_env(env, "type", org_cherry_core_type);
proc_to_env(env, "+", org_cherry_core_add);
proc_to_env(env, "-", org_cherry_core_sub);
proc_to_env(env, "*", org_cherry_core_mul);
proc_to_env(env, "/", org_cherry_core_div);
return env;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment