eval if statement, num2bool conversion
This commit is contained in:
parent
97a04bd1ce
commit
7ace1d6fe9
102
tokenize.l
102
tokenize.l
|
@ -1,5 +1,30 @@
|
|||
/* llm - litle lisp machine:
|
||||
* Author: Christian Barthel <bch@online.de>
|
||||
*
|
||||
* Copyright (c) 2019 Christian Barthel <bch@online.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* Compile: flex tokenize.l
|
||||
* cc lex.yy.c -lfl
|
||||
*/
|
||||
|
@ -70,17 +95,24 @@ nil { yylval = 0; return BOOL; }
|
|||
%%
|
||||
|
||||
/*
|
||||
* Goal: write LISP read-eval-print Loop and support
|
||||
* @ Functions
|
||||
* t,nil boolean (nand 0 1) -> boolean
|
||||
* "str" Strings (streq str1 str2) -> boolean
|
||||
* abc Symboles (symeq s1 s2) -> boolean
|
||||
* 1234 Number/Integer [add,inv] -> num
|
||||
* [lt] -> boolean
|
||||
* [num-to-bool] -> boolean
|
||||
* Goal: evaluate simple LISP forms in an
|
||||
* read-eval-print stylized loop. supports:
|
||||
*
|
||||
* Data types:
|
||||
* # Functions
|
||||
* t,nil boolean (nand <bool> <bool>) -> boolean
|
||||
* "str" Strings (streq <string> <string>) -> boolean
|
||||
* abc Symboles (symeq <sym> <sym>) -> boolean
|
||||
* 1234 Number/Integer (inv <num>) -> -num
|
||||
* (add <num> <num>) -> num
|
||||
* (lt <num> <num>) -> boolean
|
||||
* (num2bool <num>) -> boolean
|
||||
*
|
||||
* Special Forms:
|
||||
* (def <var> <symbol,number,#function)
|
||||
* (lambda (<symbol> ..) (<sym..> ))
|
||||
* Bind symbol <var> in the current environment to
|
||||
* the evaluated form.
|
||||
* (lm (<symbol> ..) (<sym..> ))
|
||||
* (if <bool> <body> <else>)
|
||||
* (quote a) -> a
|
||||
*/
|
||||
|
@ -170,6 +202,7 @@ int token_is_internal(struct token *t) {
|
|||
else if (strcmp(t->v.str, "lt") == 0) return 1;
|
||||
else if (strcmp(t->v.str, "nand") == 0) return 1;
|
||||
else if (strcmp(t->v.str, "q") == 0) return 1;
|
||||
else if (strcmp(t->v.str, "num2bool") == 0) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
@ -267,6 +300,29 @@ eval_def(struct ast *a, struct env *e)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* (if <cond:bool> <expression> <expression>) */
|
||||
struct ast *
|
||||
eval_if(struct ast *a, struct env *e)
|
||||
{
|
||||
a = a->next;
|
||||
|
||||
assert(a != NULL && a->next != NULL);
|
||||
|
||||
struct ast *condition = eval(a, e);
|
||||
|
||||
assert(condition != NULL &&
|
||||
condition->type == AST_TOK &&
|
||||
condition->v.token->type == BOOL);
|
||||
|
||||
assert(a->next != NULL &&
|
||||
a->next->next != NULL);
|
||||
|
||||
if (condition->v.token->v.num == 1)
|
||||
return eval(a->next, e);
|
||||
else
|
||||
return eval(a->next->next, e);
|
||||
}
|
||||
|
||||
/* (nand <ausdruck::bool> <audsruck::bool>) -> BOOL */
|
||||
struct ast *
|
||||
eval_nand(struct ast *a, struct env *e)
|
||||
|
@ -362,6 +418,24 @@ eval_inv(struct ast *a, struct env *e)
|
|||
NULL));
|
||||
}
|
||||
|
||||
/* (num2bool <ausdruck::NUM>) -> bool */
|
||||
struct ast *
|
||||
eval_num2bool(struct ast *a, struct env *e)
|
||||
{
|
||||
assert(a != NULL &&
|
||||
a->next != NULL &&
|
||||
a->next->next == NULL);
|
||||
struct ast *op = eval(a->next, e);
|
||||
assert(op != NULL &&
|
||||
op->type == AST_TOK &&
|
||||
op->v.token->type == NUM &&
|
||||
op->next == NULL);
|
||||
return make_ast(AST_TOK,
|
||||
make_token(BOOL,
|
||||
op->v.token->v.num != 0,
|
||||
NULL));
|
||||
}
|
||||
|
||||
struct ast *
|
||||
eval_internal_sym(struct ast *a, struct env *e)
|
||||
{
|
||||
|
@ -369,6 +443,7 @@ eval_internal_sym(struct ast *a, struct env *e)
|
|||
return eval_def(a, e);
|
||||
else if (strcmp(a->v.token->v.str, "lm") == 0) {
|
||||
} else if (strcmp(a->v.token->v.str, "if") == 0) {
|
||||
return eval_if(a, e);
|
||||
} else if (strcmp(a->v.token->v.str, "inv") == 0) {
|
||||
return eval_inv(a, e);
|
||||
} else if (strcmp(a->v.token->v.str, "add") == 0) {
|
||||
|
@ -380,6 +455,8 @@ eval_internal_sym(struct ast *a, struct env *e)
|
|||
} else if (strcmp(a->v.token->v.str, "q") == 0) {
|
||||
//return make_ast(AST_QUOTE, a->next);
|
||||
return a->next;
|
||||
} else if (strcmp(a->v.token->v.str, "num2bool") == 0) {
|
||||
return eval_num2bool(a, e);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -446,6 +523,11 @@ pr(struct ast *a)
|
|||
else
|
||||
printf("nil\n");
|
||||
}
|
||||
break;
|
||||
case AST_LIST:
|
||||
printf("#fn\n");
|
||||
default:
|
||||
err(1, "don't know how to print");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue