1#include <stdio.h>2#include <semaphore.h>3#include <pthread.h>4#include <unistd.h>56#include <sys/queue.h>78#include "env.h"9#include "scanner.h"10#include "parser.h"11#include "eval.h"1213evalerr eval(env *e, statement **s);1415evalerr16evalop(binop op, int arg1, int arg2, int *dest)17{18 switch (op) {19 case OP_PLUS:20 if (__builtin_sadd_overflow(arg1, arg2, dest))21 return ERR_PRECISION;22 break;23 case OP_MINUS:24 if (__builtin_ssub_overflow(arg1, arg2, dest))25 return ERR_PRECISION;26 break;27 case OP_MULTI:28 if (__builtin_smul_overflow(arg1, arg2, dest))29 return ERR_PRECISION;30 break;31 case OP_DIVIDE:32 if (arg2 == 0)33 return ERR_DIVBYZERO;3435 *dest = arg1 / arg2;36 break;37 }3839 return EVAL_OK;40}4142evalerr43evaluate(env *vars, expr *exp, int *dest)44{45 evalerr ret;46 int ee1, ee2;47 expr *exp1, *exp2;4849 switch (exp->type) {50 case EXP_LIT:51 *dest = exp->d.literal.num;52 break;53 case EXP_VAR:54 if (getval(vars, exp->d.variable.var, dest))55 return ERR_UNDEFVAR;56 else57 break;58 case EXP_BIN:59 exp1 = exp->d.operation.expr1;60 exp2 = exp->d.operation.expr2;6162 if ((ret = evaluate(vars, exp1, &ee1)) != EVAL_OK ||63 (ret = evaluate(vars, exp2, &ee2)) != EVAL_OK)64 return ret;6566 if ((ret = evalop(exp->d.operation.op, ee1, ee2, dest))67 != EVAL_OK)68 return ret;6970 break;71 }7273 return EVAL_OK;74}7576evalerr77execdefine(env *vars, statement *stmt)78{79 evalerr ret;80 int value;8182 if ((ret = evaluate(vars, stmt->d.define.exp, &value))83 != EVAL_OK)84 return ret;8586 if (setval(vars, stmt->d.define.var, value))87 return ERR_VARDEFINED;8889 return EVAL_OK;90}9192evalerr93execassign(env *vars, statement *stmt)94{95 evalerr ret;96 int value;9798 if ((ret = evaluate(vars, stmt->d.assign.exp, &value))99 != EVAL_OK)100 return ret;101102 if (updval(vars, stmt->d.assign.var, value))103 return ERR_UNINITVAR;104105 return EVAL_OK;106}107108evalerr109execread(env *vars, statement *stmt)110{111 int input;112113 if (isatty(0) && printf("Input: ") <= 0)114 return ERR_PRINTF;115 if (fflush(stdout))116 return ERR_FLUSH;117118 if (scanf("%d", &input) == EOF)119 return ERR_SCANF;120 if (updval(vars, stmt->d.read.var, input))121 return ERR_UNINITVAR;122123 return EVAL_OK;124}125126evalerr127execwrite(env *vars, statement *stmt)128{129 evalerr ret;130 int value;131132 if ((ret = evaluate(vars, stmt->d.write.exp, &value))133 != EVAL_OK)134 return ret;135136 if (isatty(0)) {137 if (printf("Value: %d\n", value) <= 0)138 return ERR_PRINTF;139 } else {140 printf("%d\n", value);141 }142143 return EVAL_OK;144}145146evalerr147execcond(env *vars, statement *stmt)148{149 evalerr ret;150 int value;151152 if ((ret = evaluate(vars, stmt->d.cond.cond, &value))153 != EVAL_OK)154 return ret;155156 if (value == 0)157 return eval(vars, stmt->d.cond.brn2);158 else159 return eval(vars, stmt->d.cond.brn1);160}161162evalerr163execloop(env *vars, statement *stmt)164{165 evalerr ret;166 int value;167168 if ((ret = evaluate(vars, stmt->d.loop.cond, &value))169 != EVAL_OK)170 return ret;171172 while (value != 0) {173 if ((ret = eval(vars, stmt->d.loop.brn)) != EVAL_OK)174 return ret;175176 if ((ret = evaluate(vars, stmt->d.loop.cond, &value))177 != EVAL_OK)178 return ret;179 }180181 return EVAL_OK;182}183184evalerr185execute(env *vars, statement *stmt)186{187 switch (stmt->type) {188 case STMT_ERROR:189 break; /* Never reached */190 case STMT_DEFINE:191 return execdefine(vars, stmt);192 case STMT_ASSIGN:193 return execassign(vars, stmt);194 case STMT_READ:195 return execread(vars, stmt);196 case STMT_WRITE:197 return execwrite(vars, stmt);198 case STMT_COND:199 return execcond(vars, stmt);200 case STMT_LOOP:201 return execloop(vars, stmt);202 }203204 /* Never reached. */205 return EVAL_OK;206}207208evalerr209eval(env *vars, statement **cmds)210{211 evalerr ret;212 statement *stmt;213214 while ((stmt = *cmds++))215 if ((ret = execute(vars, stmt)) != EVAL_OK)216 return ret;217218 return EVAL_OK;219}