Last active
December 29, 2015 02:59
-
-
Save semahawk/7604599 to your computer and use it in GitHub Desktop.
Just me trying to get some grasp around the execution order of an AST. Huh.... Nevermind that crap..
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* | |
* exec_order.c | |
* | |
* Created at: Fri 22 Nov 16:52:08 2013 16:52:08 | |
* | |
* Author: Szymon Urbaś <[email protected]> | |
* | |
* License: MIT (X11) | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stddef.h> | |
#include <err.h> | |
/* current node's id */ | |
static unsigned currid; | |
/* {{{ type defs */ | |
enum type { | |
VARIABLE, INT, | |
ASSIGNMENT, ADDITION, SUBSTRACTION | |
}; | |
#define NODE_BASE \ | |
enum type type; \ | |
struct node *next; \ | |
void (*dumpf)(struct node *); \ | |
void (*execf)(struct node *); \ | |
unsigned id; \ | |
int value; | |
struct node { | |
NODE_BASE | |
}; | |
struct node_binop { | |
NODE_BASE | |
struct node *left, *right; | |
}; | |
/* }}} */ | |
/* {{{ nodes 'line' */ | |
static struct node *nodes[16]; | |
static struct node **nodes_curr = nodes; | |
/* }}} */ | |
/* {{{ the arguments stack */ | |
static int stack[16]; | |
static int *stack_curr = stack; | |
static void push(int value) | |
{ | |
*stack_curr = value; | |
stack_curr++; | |
} | |
static int pop(void) | |
{ | |
int save = *stack_curr; | |
stack_curr--; | |
return save; | |
} | |
static void dump_stack(void) | |
{ | |
int i = 0; | |
printf("\nStack Dump:\n"); | |
for (; i < sizeof(stack) / sizeof(stack[0]); i++){ | |
printf(" %x - %d\n", i, stack[i]); | |
} | |
} | |
/* }}} */ | |
/* {{{ some debugging/macros stuff */ | |
static unsigned sw; | |
#define INDENT do { sw += 2; } while (0) | |
#define DEDENT do { sw -= 2; } while (0) | |
#define TABS do { int i = 0; for (; i < sw; i++){ putchar(' ');} } while (0) | |
/* two handy macros */ | |
#define DUMP(node) (node)->dumpf(node) | |
#define EXEC(node) (node)->execf(node) | |
/* macro to print the node's id */ | |
#define ID(node) printf("%d. %p ", (node)->id, (void *)(node)) | |
const char *ttos(enum type type) | |
{ | |
switch (type){ | |
case VARIABLE: return "variable"; | |
case INT: return "integer"; | |
case ASSIGNMENT: return "op '='"; | |
case ADDITION: return "op '+'"; | |
case SUBSTRACTION: return "op '-'"; | |
} | |
return "#unknown#"; | |
} | |
/* }}} */ | |
/* {{{ dumping functions */ | |
void dump(struct node *node) | |
{ | |
ID(node); | |
TABS; | |
printf("- %s (%d)\n", ttos(node->type), node->value); | |
} | |
void dump_binop(struct node *n) | |
{ | |
struct node_binop *node = (struct node_binop *)n; | |
ID(node); | |
TABS; | |
printf("= %s\n", ttos(node->type)); | |
INDENT; | |
DUMP(node->left); | |
DUMP(node->right); | |
DEDENT; | |
} | |
/* }}} */ | |
/* {{{ executing functions */ | |
/* constant (integer) */ | |
void cons(struct node *n) | |
{ | |
static int currval = 1; | |
printf("push %d (integer)\n", n->value); | |
push(n->value); | |
} | |
/* variable */ | |
void var(struct node *n) | |
{ | |
printf("push %d (variable)\n", n->value); | |
push(n->value); | |
} | |
/* assignment */ | |
void assign(struct node *n) | |
{ | |
int FOS = pop(); | |
int SOS = pop(); | |
printf("push %d (assign)\n", SOS); | |
push(SOS); | |
} | |
/* addition */ | |
void add(struct node *n) | |
{ | |
int FOS = pop(); | |
int SOS = pop(); | |
printf("push %d (add)\n", SOS + FOS); | |
push(SOS + FOS); | |
} | |
/* substraction */ | |
void sub(struct node *n) | |
{ | |
int FOS = pop(); | |
int SOS = pop(); | |
printf("push %d (sub)\n", SOS - FOS); | |
push(SOS - FOS); | |
} | |
/* }}} */ | |
/* {{{ new node functions */ | |
#define PUSH_NODE(node) do { \ | |
*nodes_curr = node; \ | |
nodes_curr++; \ | |
} while (0); | |
struct node *new(enum type type, int value) | |
{ | |
struct node *n = malloc(sizeof(struct node)); | |
if (!n) | |
err(1, "malloc"); | |
PUSH_NODE(n); | |
n->id = currid++; | |
n->type = type; | |
n->value = value; | |
n->next = NULL; | |
n->dumpf = dump; | |
if (type == INT) | |
n->execf = cons; | |
else if (type == VARIABLE) | |
n->execf = var; | |
else | |
n->execf = NULL; | |
return n; | |
} | |
struct node *new_binop(enum type type, struct node *left, struct node *right) | |
{ | |
struct node_binop *n = malloc(sizeof(struct node_binop)); | |
if (!n) | |
err(1, "malloc"); | |
PUSH_NODE((struct node *)n); | |
n->id = currid++; | |
n->type = type; | |
n->value = -1; | |
n->left = left; | |
n->right = right; | |
n->dumpf = dump_binop; | |
if (type == ASSIGNMENT) | |
n->execf = assign; | |
else if (type == ADDITION) | |
n->execf = add; | |
else if (type == SUBSTRACTION) | |
n->execf = sub; | |
else | |
n->execf = NULL; | |
return (struct node *)n; | |
} | |
/* }}} */ | |
int main(void) | |
{ | |
struct node *n = | |
new_binop(ADDITION, | |
new(VARIABLE, 1), | |
new_binop(ADDITION, | |
new_binop(ADDITION, | |
new(INT, 2), | |
new(VARIABLE, 3)), | |
new(INT, 4))); | |
struct node *p; | |
struct node **pp; | |
printf("The 'Code' (a = 1, b = 3):\n\n"); | |
printf(" a + ((2 + b) + 4)\n\n"); | |
printf("The Tree:\n"); | |
for (p = n; p != NULL; p = p->next){ | |
DUMP(p); | |
} | |
printf("\nThe Execution Order:\n"); | |
for (pp = nodes; *pp != NULL; pp++){ | |
ID(*pp); | |
printf("%s\n", ttos((*pp)->type)); | |
} | |
printf("\nExecuting Nodes:\n"); | |
for (pp = nodes; *pp != NULL; pp++){ | |
ID(*pp); | |
EXEC(*pp); | |
} | |
return 0; | |
} | |
/* | |
* vi: ft=c:ts=2:sw=2:expandtab | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment