Code generation will have no access to the token numbers assigned by the
parser, so we create our own numbering scheme and translate between
parsing and code generation.
---
 software/libfpvm/ast.h    |   33 +++++++++++++++++++-
 software/libfpvm/fpvm.c   |   73 ++++++++++++++++++++++-----------------------
 software/libfpvm/parser.y |   33 +++++++++++++++++++-
 3 files changed, 99 insertions(+), 40 deletions(-)

diff --git a/software/libfpvm/ast.h b/software/libfpvm/ast.h
index cc170f1..95cb902 100644
--- a/software/libfpvm/ast.h
+++ b/software/libfpvm/ast.h
@@ -20,7 +20,36 @@
 
 #define NDEBUG
 
-#define IDENTIFIER_SIZE 24
+enum ast_op {
+       op_trouble,     /* null value */
+       op_ident,
+       op_constant,
+       op_plus,
+       op_minus,
+       op_multiply,
+       op_divide,
+       op_percent,
+       op_abs,
+       op_isin,
+       op_icos,
+       op_sin,
+       op_cos,
+       op_above,
+       op_below,
+       op_equal,
+       op_i2f,
+       op_f2i,
+       op_if,
+       op_tsign,
+       op_quake,
+       op_not,
+       op_sqr,
+       op_sqrt,
+       op_invsqrt,
+       op_min,
+       op_max,
+       op_int,
+};
 
 struct id {
        int token;
@@ -36,7 +65,7 @@ struct ast_branches {
 };
 
 struct ast_node {
-       int token;
+       enum ast_op op;
        /*
         * label is an empty string:
         *   node is a constant
diff --git a/software/libfpvm/fpvm.c b/software/libfpvm/fpvm.c
index 2600e63..c97e73c 100644
--- a/software/libfpvm/fpvm.c
+++ b/software/libfpvm/fpvm.c
@@ -24,7 +24,6 @@
 #include "ast.h"
 #include "unique.h"
 #include "parser_helper.h"
-#include "parser.h"
 
 const char *fpvm_version()
 {
@@ -236,22 +235,22 @@ static int add_isn(struct fpvm_fragment *fragment, int 
opcode,
        return 1;
 }
 
-static int operator2opcode(int token)
+static int operator2opcode(enum ast_op op)
 {
-       switch (token) {
-       case TOK_PLUS:          return FPVM_OPCODE_FADD;
-       case TOK_MINUS:         return FPVM_OPCODE_FSUB;
-       case TOK_MULTIPLY:      return FPVM_OPCODE_FMUL;
-       case TOK_ABS:           return FPVM_OPCODE_FABS;
-       case TOK_ISIN:          return FPVM_OPCODE_SIN;
-       case TOK_ICOS:          return FPVM_OPCODE_COS;
-       case TOK_ABOVE:         return FPVM_OPCODE_ABOVE;
-       case TOK_EQUAL:         return FPVM_OPCODE_EQUAL;
-       case TOK_I2F:           return FPVM_OPCODE_I2F;
-       case TOK_F2I:           return FPVM_OPCODE_F2I;
-       case TOK_IF:            return FPVM_OPCODE_IF;
-       case TOK_TSIGN:         return FPVM_OPCODE_TSIGN;
-       case TOK_QUAKE:         return FPVM_OPCODE_QUAKE;
+       switch (op) {
+       case op_plus:           return FPVM_OPCODE_FADD;
+       case op_minus:          return FPVM_OPCODE_FSUB;
+       case op_multiply:       return FPVM_OPCODE_FMUL;
+       case op_abs:            return FPVM_OPCODE_FABS;
+       case op_isin:           return FPVM_OPCODE_SIN;
+       case op_icos:           return FPVM_OPCODE_COS;
+       case op_above:          return FPVM_OPCODE_ABOVE;
+       case op_equal:          return FPVM_OPCODE_EQUAL;
+       case op_i2f:            return FPVM_OPCODE_I2F;
+       case op_f2i:            return FPVM_OPCODE_F2I;
+       case op_if:             return FPVM_OPCODE_IF;
+       case op_tsign:          return FPVM_OPCODE_TSIGN;
+       case op_quake:          return FPVM_OPCODE_QUAKE;
        default:
                return -1;
        }
@@ -349,8 +348,8 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
        int opa, opb;
        int opcode;
 
-       switch(node->token) {
-       case TOK_CONSTANT:
+       switch(node->op) {
+       case op_constant:
                /* AST node is a constant */
                opa = REG_CONST(node->contents.constant);
                if(reg != FPVM_INVALID_REG)
@@ -358,7 +357,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
                else
                        reg = opa;
                return reg;
-       case TOK_IDENT:
+       case op_ident:
                /* AST node is a variable */
                if(fragment->bind_mode) {
                        opa = sym_to_reg(fragment, node->label, 0, NULL);
@@ -378,7 +377,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
                else
                        reg = opa;
                return reg;
-       case TOK_IF:
+       case op_if:
                /*
                 * "if" must receive a special treatment.
                 * It is implemented as a ternary function,
@@ -391,8 +390,8 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
                opb = COMPILE(FPVM_INVALID_REG, node->contents.branches.c);
                COMPILE(FPVM_REG_IFB, node->contents.branches.a);
                break;
-       case TOK_NOT:
-               if(node->contents.branches.a->token == TOK_CONSTANT) {
+       case op_not:
+               if(node->contents.branches.a->op == op_constant) {
                        /* Node is a negative constant */
                        struct ast_node *n;
 
@@ -418,15 +417,15 @@ static int compile(struct fpvm_fragment *fragment, int 
reg, struct ast_node *nod
        if(reg == FPVM_INVALID_REG)
                reg = fragment->next_sur--;
 
-       switch(node->token) {
-       case TOK_BELOW:
+       switch(node->op) {
+       case op_below:
                /*
                 * "below" is like "above", but with reversed operands.
                 */
                ADD_ISN(FPVM_OPCODE_ABOVE, opb, opa, reg);
                break;
-       case TOK_SIN:
-       case TOK_COS: {
+       case op_sin:
+       case op_cos: {
                /*
                 * Trigo functions are implemented with several instructions.
                 * We must convert the floating point argument in radians
@@ -436,7 +435,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
                int reg_mul = REG_ALLOC();
                int reg_f2i = REG_ALLOC();
 
-               if(node->token == TOK_SIN)
+               if(node->op == op_sin)
                        opcode = FPVM_OPCODE_SIN;
                else
                        opcode = FPVM_OPCODE_COS;
@@ -446,7 +445,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
                ADD_ISN(opcode, reg_f2i, 0, reg);
                break;
        }
-       case TOK_SQRT: {
+       case op_sqrt: {
                /*
                 * Square root is implemented with a variant of the Quake III
                 * algorithm.
@@ -459,10 +458,10 @@ static int compile(struct fpvm_fragment *fragment, int 
reg, struct ast_node *nod
                ADD_ISN(FPVM_OPCODE_FMUL, opa, reg_invsqrt, reg);
                break;
        }
-       case TOK_INVSQRT:
+       case op_invsqrt:
                ADD_INV_SQRT(opa, reg);
                break;
-       case TOK_DIVIDE: {
+       case op_divide: {
                /*
                 * Floating point division is implemented as
                 * a/b = a*(1/sqrt(b))*(1/sqrt(b))
@@ -482,7 +481,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
                ADD_ISN(FPVM_OPCODE_FMUL, reg_invsqrt2, reg_a2, reg);
                break;
        }
-       case TOK_PERCENT: {
+       case op_percent: {
                int reg_invsqrt = REG_ALLOC();
                int reg_invsqrt2 = REG_ALLOC();
                int reg_div = REG_ALLOC();
@@ -498,21 +497,21 @@ static int compile(struct fpvm_fragment *fragment, int 
reg, struct ast_node *nod
                ADD_ISN(FPVM_OPCODE_FSUB, opa, reg_bidiv, reg);
                break;
        }
-       case TOK_MIN:
+       case op_min:
                ADD_ISN(FPVM_OPCODE_ABOVE, opa, opb, FPVM_REG_IFB);
                ADD_ISN(FPVM_OPCODE_IF, opb, opa, reg);
                break;
-       case TOK_MAX:
+       case op_max:
                ADD_ISN(FPVM_OPCODE_ABOVE, opa, opb, FPVM_REG_IFB);
                ADD_ISN(FPVM_OPCODE_IF, opa, opb, reg);
                break;
-       case TOK_SQR:
+       case op_sqr:
                ADD_ISN(FPVM_OPCODE_FMUL, opa, opa, reg);
                break;
-       case TOK_INT:
+       case op_int:
                ADD_INT(opa, reg);
                break;
-       case TOK_NOT:
+       case op_not:
                opb = find_negative_constant(fragment);
                if(opb == FPVM_INVALID_REG)
                        return FPVM_INVALID_REG;
@@ -520,7 +519,7 @@ static int compile(struct fpvm_fragment *fragment, int reg, 
struct ast_node *nod
                break;
        default:
                /* Normal case */
-               opcode = operator2opcode(node->token);
+               opcode = operator2opcode(node->op);
                if(opcode < 0) {
                        snprintf(fragment->last_error, FPVM_MAXERRLEN,
                            "Operation not supported: %s", node->label);
diff --git a/software/libfpvm/parser.y b/software/libfpvm/parser.y
index 21affe0..cfd2013 100644
--- a/software/libfpvm/parser.y
+++ b/software/libfpvm/parser.y
@@ -25,13 +25,44 @@
        #include "parser.h"
 
 
+       const enum ast_op tok2op[] = {
+               [TOK_IDENT]     = op_ident,
+               [TOK_CONSTANT]  = op_constant,
+               [TOK_PLUS]      = op_plus,
+               [TOK_MINUS]     = op_minus,
+               [TOK_MULTIPLY]  = op_multiply,
+               [TOK_DIVIDE]    = op_divide,
+               [TOK_PERCENT]   = op_percent,
+               [TOK_ABS]       = op_abs,
+               [TOK_ISIN]      = op_isin,
+               [TOK_ICOS]      = op_icos,
+               [TOK_SIN]       = op_sin,
+               [TOK_COS]       = op_cos,
+               [TOK_ABOVE]     = op_above,
+               [TOK_BELOW]     = op_below,
+               [TOK_EQUAL]     = op_equal,
+               [TOK_I2F]       = op_i2f,
+               [TOK_F2I]       = op_f2i,
+               [TOK_IF]        = op_if,
+               [TOK_TSIGN]     = op_tsign,
+               [TOK_QUAKE]     = op_quake,
+               [TOK_NOT]       = op_not,
+               [TOK_SQR]       = op_sqr,
+               [TOK_SQRT]      = op_sqrt,
+               [TOK_INVSQRT]   = op_invsqrt,
+               [TOK_MIN]       = op_min,
+               [TOK_MAX]       = op_max,
+               [TOK_INT]       = op_int,
+               
+       };
+
        struct ast_node *node(int token, const char *id, struct ast_node *a,
             struct ast_node *b, struct ast_node *c)
        {
                struct ast_node *n;
 
                n = malloc(sizeof(struct ast_node));
-               n->token = token;
+               n->op = tok2op[token];
                n->label = id;
                n->contents.branches.a = a;
                n->contents.branches.b = b;
-- 
1.7.1

_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode

Reply via email to