/* This file is part of GCC.
GCC 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, or (at your option) any later
version.
GCC 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 GCC; see the file COPYING3. If not see
. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
gpy_object_t ** __GPY_GLOBL_RR_STACK;
gpy_vector_t * __GPY_GLOBL_CALL_STACK;
gpy_vector_t * __GPY_GLOBL_PRIMITIVES;
gpy_object_t ** __GPY_GLOBL_RETURN_ADDR;
gpy_object_t ** __GPY_GLOBL_RR_STACK_POINTER;
/*
size
current_length
return addr
.... symbols
*/
static
void gpy_rr_init_primitives (void)
{
gpy_obj_integer_mod_init (__GPY_GLOBL_PRIMITIVES);
gpy_obj_staticmethod_mod_init (__GPY_GLOBL_PRIMITIVES);
gpy_obj_class_mod_init (__GPY_GLOBL_PRIMITIVES);
gpy_obj_classmethod_mod_init (__GPY_GLOBL_PRIMITIVES);
}
static
void gpy_rr_init_runtime_stack (void)
{
__GPY_GLOBL_PRIMITIVES = gpy_malloc (sizeof (gpy_vector_t));
gpy_vec_init (__GPY_GLOBL_PRIMITIVES);
gpy_rr_init_primitives ();
__GPY_GLOBL_CALL_STACK = gpy_malloc (sizeof (gpy_vector_t));
gpy_vec_init (__GPY_GLOBL_CALL_STACK);
__GPY_GLOBL_RR_STACK = gpy_calloc (3, sizeof (gpy_object_t *));
*__GPY_GLOBL_RR_STACK = gpy_rr_fold_integer (2);
__GPY_GLOBL_RR_STACK_POINTER = __GPY_GLOBL_RR_STACK;
__GPY_GLOBL_RR_STACK_POINTER++;
*__GPY_GLOBL_RR_STACK_POINTER = gpy_rr_fold_integer (0);
__GPY_GLOBL_RR_STACK_POINTER++;
*__GPY_GLOBL_RR_STACK_POINTER = NULL;
__GPY_GLOBL_RETURN_ADDR = __GPY_GLOBL_RR_STACK_POINTER;
}
/* remember to update the stack pointer's and the stack size */
void gpy_rr_extend_runtime_stack (int nslots)
{
size_t size = sizeof (gpy_object_t *) * (3+nslots);
__GPY_GLOBL_RR_STACK = gpy_realloc (__GPY_GLOBL_RR_STACK, size);
__GPY_GLOBL_RR_STACK_POINTER = __GPY_GLOBL_RR_STACK;
__GPY_GLOBL_RR_STACK_POINTER += 3 + nslots;
}
void gpy_rr_init_runtime (void)
{
gpy_rr_init_runtime_stack ();
}
void gpy_rr_cleanup_final (void)
{
/*
Cleanup the runtime stack and all other object data
*/
mpfr_free_cache ();
}
gpy_object_attrib_t * gpy_rr_fold_attribute (const unsigned char * identifier,
unsigned char * code_addr,
unsigned int offset)
{
gpy_object_attrib_t * attrib = gpy_malloc (sizeof (gpy_object_attrib_t));
attrib->identifier = identifier;
if (code_addr)
{
gpy_object_t * f = gpy_rr_fold_classmethod_decl (identifier, code_addr);
attrib->addr = f;
}
else
attrib->addr = NULL;
attrib->offset = offset;
return attrib;
}
gpy_object_attrib_t ** gpy_rr_fold_attrib_list (int n, ...)
{
gpy_object_attrib_t ** retval = NULL;
if (n > 0)
{
/* +1 for the sentinal */
retval = (gpy_object_attrib_t **)
gpy_calloc (n+1, sizeof (gpy_object_attrib_t *));
va_list ap;
int idx;
va_start (ap, n);
for (idx = 0; idx < n; ++idx)
{
gpy_object_attrib_t * i = va_arg (ap, gpy_object_attrib_t *);
retval[idx] = i;
}
/* sentinal */
retval[idx] = NULL;
}
return retval;
}
gpy_object_t * gpy_rr_fold_class_decl (gpy_object_attrib_t ** attribs,
int size, const char * identifier)
{
gpy_object_t * retval = NULL_OBJECT;
gpy_object_t ** args = (gpy_object_t **)
gpy_calloc (4, sizeof(gpy_object_t*));
gpy_literal_t A;
A.type = TYPE_ATTRIB_L;
A.literal.attribs = attribs;
gpy_literal_t i;
i.type = TYPE_INTEGER;
i.literal.integer = size;
gpy_literal_t s;
s.type = TYPE_STRING;
s.literal.string = (char *) identifier;
gpy_object_t a1 = { .T = TYPE_OBJECT_LIT, .o.literal = &A };
gpy_object_t a2 = { .T = TYPE_OBJECT_LIT, .o.literal = &i };
gpy_object_t a3 = { .T = TYPE_OBJECT_LIT, .o.literal = &s };
gpy_object_t a4 = { .T = TYPE_NULL, .o.literal = NULL };
args[0] = &a1;
args[1] = &a2;
args[2] = &a3;
args[3] = &a4;
gpy_typedef_t * def = __gpy_class_type_node;
retval = def->tp_new (def, args);
gpy_free (args);
gpy_assert (retval->T == TYPE_OBJECT_DECL);
return retval;
}
gpy_object_t * gpy_rr_fold_staticmethod_decl (const char * identifier,
unsigned char * code_addr)
{
gpy_object_t * retval = NULL_OBJECT;
gpy_object_t ** args = (gpy_object_t **)
gpy_calloc (4, sizeof(gpy_object_t*));
gpy_literal_t i;
i.type = TYPE_STRING;
i.literal.string = (char *)identifier;
gpy_literal_t p;
p.type = TYPE_ADDR;
p.literal.addr = code_addr;
gpy_literal_t n;
n.type = TYPE_INTEGER;
n.literal.integer = 0;
gpy_object_t a1 = { .T = TYPE_OBJECT_LIT, .o.literal = &i };
gpy_object_t a2 = { .T = TYPE_OBJECT_LIT, .o.literal = &p };
gpy_object_t a3 = { .T = TYPE_OBJECT_LIT, .o.literal = &n };
gpy_object_t a4 = { .T = TYPE_NULL, .o.literal = NULL };
args[0] = &a1;
args[1] = &a2;
args[2] = &a3;
args[3] = &a4;
gpy_typedef_t * def = __gpy_staticmethod_type_node;
retval = def->tp_new (def, args);
gpy_free (args);
gpy_assert (retval->T == TYPE_OBJECT_DECL);
return retval;
}
gpy_object_t * gpy_rr_fold_classmethod_decl (const char * identifier,
unsigned char * code_addr)
{
gpy_object_t * retval = NULL_OBJECT;
gpy_object_t ** args = (gpy_object_t **)
gpy_calloc (4, sizeof(gpy_object_t*));
gpy_literal_t s;
s.type = TYPE_STRING;
s.literal.string = (char *)identifier;
gpy_literal_t p;
p.type = TYPE_ADDR;
p.literal.addr = code_addr;
gpy_literal_t n;
n.type = TYPE_INTEGER;
n.literal.integer = 0;
gpy_object_t a1 = { .T = TYPE_OBJECT_LIT, .o.literal = &s };
gpy_object_t a2 = { .T = TYPE_OBJECT_LIT, .o.literal = &p };
gpy_object_t a3 = { .T = TYPE_OBJECT_LIT, .o.literal = &n };
gpy_object_t a4 = { .T = TYPE_NULL, .o.literal = NULL };
args[0] = &a1;
args[1] = &a2;
args[2] = &a3;
args[3] = &a4;
gpy_typedef_t * def = __gpy_classmethod_type_node;
retval = def->tp_new (def, args);
gpy_free (args);
gpy_assert (retval->T == TYPE_OBJECT_DECL);
return retval;
}
gpy_object_t * gpy_rr_fold_call (gpy_object_t * decl, int nargs, ...)
{
gpy_object_t * retval = NULL_OBJECT;
gpy_assert (decl->T == TYPE_OBJECT_DECL);
gpy_typedef_t * type = decl->o.object_state->definition;
/* + 1 for sentinal */
gpy_object_t ** args = calloc (nargs + 1, sizeof (gpy_object_t *));
va_list ap;
int idx;
va_start (ap, nargs);
for (idx = 0; idx < nargs; ++idx)
{
args[idx] = va_arg (ap, gpy_object_t *);
}
args[idx] = NULL;
if (type->tp_call)
{
retval = type->tp_call (decl, args);
}
else
fatal ("name is not callable!\n");
return retval;
}
unsigned char * gpy_rr_eval_attrib_reference (gpy_object_t * base,
const char * attrib)
{
unsigned char * retval = NULL;
gpy_typedef_t * type = base->o.object_state->definition;
struct gpy_object_attrib_t ** members = type->members_defintion;
gpy_object_state_t * objs = base->o.object_state;
int idx, offset = -1;
for (idx = 0; members[idx] != NULL; ++idx)
{
struct gpy_object_attrib_t * it = members[idx];
if (!strcmp (attrib, it->identifier))
{
offset = it->offset;
unsigned char * state = (unsigned char *)objs->state;
retval = state + offset;
break;
}
}
gpy_assert (retval);
return retval;
}
gpy_object_t * gpy_rr_fold_integer (const int x)
{
gpy_object_t * retval = NULL_OBJECT;
gpy_object_t ** args = (gpy_object_t **)
gpy_calloc (2, sizeof(gpy_object_t*));
gpy_literal_t i;
i.type = TYPE_INTEGER;
i.literal.integer = x;
gpy_object_t a1 = { .T = TYPE_OBJECT_LIT, .o.literal = &i };
gpy_object_t a2 = { .T = TYPE_NULL, .o.literal = NULL };
args[0] = &a1;
args[1] = &a2;
gpy_typedef_t * Int_def = __gpy_integer_type_node;
retval = Int_def->tp_new (Int_def, args);
gpy_free(args);
gpy_assert (retval->T == TYPE_OBJECT_STATE);
return retval;
}
inline
void * gpy_rr_get_object_state (gpy_object_t * o)
{
gpy_assert (o);
return o->o.object_state->state;
}
/**
* int fd: we could use bit masks to represent:
* stdout/stderr ...
**/
void gpy_rr_eval_print (int fd, int count, ...)
{
va_list vl; int idx;
va_start (vl,count);
gpy_object_t * it = NULL;
for (idx = 0; idxo.object_state->definition;
switch (fd)
{
case 1:
definition->tp_print (it, stdout, false);
break;
case 2:
definition->tp_print (it, stderr, false);
break;
default:
fatal ("invalid print file-descriptor <%i>!\n", fd );
break;
}
}
fprintf (stdout, "\n");
va_end (vl);
}
inline
void gpy_rr_incr_ref_count (gpy_object_t * x1)
{
gpy_assert (x1->T == TYPE_OBJECT_STATE);
gpy_object_state_t * x = x1->o.object_state;
debug ("incrementing ref count on <%p>:<%i> to <%i>!\n",
(void*) x, x->ref_count, (x->ref_count + 1));
x->ref_count++;
}
inline
void gpy_rr_decr_ref_count (gpy_object_t * x1)
{
gpy_assert (x1->T == TYPE_OBJECT_STATE);
gpy_object_state_t * x = x1->o.object_state;
debug ("decrementing ref count on <%p>:<%i> to <%i>!\n",
(void*) x, x->ref_count, (x->ref_count - 1));
x->ref_count--;
}
gpy_object_t * gpy_rr_eval_expression (gpy_object_t * x1,
gpy_object_t * y1,
unsigned int op)
{
char * op_str = NULL;
gpy_object_t * retval = NULL;
gpy_assert (x1->T == TYPE_OBJECT_STATE);
gpy_assert (y1->T == TYPE_OBJECT_STATE);
gpy_object_state_t * x = x1->o.object_state;
gpy_object_state_t * y = y1->o.object_state;
struct gpy_typedef_t * def = x1->o.object_state->definition;
struct gpy_number_prot_t * binops = (*def).binary_protocol;
struct gpy_number_prot_t binops_l = (*binops);
debug ("Eval expression!\n");
binary_op o = NULL;
switch( op )
{
/* addition */
case 1:
o = binops_l.n_add;
op_str = "+ ";
break;
/* FINISH .... */
default:
fatal("unhandled binary operation <%x>!\n", op );
break;
}
if (o)
{
#ifdef DEBUG
x->definition->tp_print (x1, stdout, false);
fprintf (stdout, "%s", op_str );
y->definition->tp_print (y1, stdout, true);
#endif
retval = o (x1,y1);
#ifdef DEBUG
fprintf (stdout, "evaluated to: ");
retval->o.object_state->definition->tp_print (retval, stdout, false);
fprintf (stdout, "!\n");
#endif
}
else
fatal ("no binary protocol!\n");
return retval;
}