Sfoglia il codice sorgente

All fields of Lambda and Closure are accessible via Object_{get,put}.

master
Ian Piumarta 1 anno fa
parent
commit
72753c6725
1 ha cambiato i file con 147 aggiunte e 76 eliminazioni
  1. +147
    -76
      minproto.leg

+ 147
- 76
minproto.leg Vedi File

@ -1,27 +1,27 @@
# minproto.leg -- minimal prototype langauge for semantic experiments
#
# last edited: 2024-05-07 23:23:22 by piumarta on m1mbp
# last edited: 2024-05-09 10:09:56 by piumarta on zora-1034.local
%{
;
#ifndef GC
# define GC 1
# define GC 1 // do not fill memory with unreachable junk
#endif
#ifndef TAGS
# define TAGS 1
# define TAGS 1 // Integer and Float are immediate values encoded in their object "pointer"
#endif
#ifndef TYPECODES
# define TYPECODES 0
#ifndef TYPECODES // <ast>.eval() dispatches using switch(), instead of invoking a method
# define TYPECODES 0 // (approx. 210% performance increase, because no dynamic dispatch in eval())
#endif
#ifndef PRIMCLOSURE
# define PRIMCLOSURE 1
#ifndef PRIMCLOSURE // Lambda and Closure are primitive types, not subtypes of Object
# define PRIMCLOSURE 0 // (approx. 6% performance decrease, because every Object_get() is slower)
#endif
#ifndef DELOPT
# define DELOPT 0
#ifndef DELOPT // delegate is a member of Object structure, not a normal property
# define DELOPT 0 // (approx. 60% performance increase, becase no associative lookup of __delegate__)
#endif
#include <math.h>
@ -114,7 +114,7 @@ doTypes(makeProto);
doProperties(declareProp);
#undef declareProp
#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last)
#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last) _(fixed)
#define declareSym(NAME) oop sym_##NAME = 0;
doSymbols(declareSym);
@ -133,7 +133,7 @@ struct Symbol { enum type type; char *name; oop value; };
struct Primitive { enum type type; oop name; prim_t function; };
#if PRIMCLOSURE
struct Lambda { enum type type; oop parameters, body; };
struct Closure { enum type type; int fixed; oop lambda, environment; };
struct Closure { enum type type; int fixed; oop function, environment; };
#endif
struct Object { enum type type; int isize, icap, psize;
# if DELOPT
@ -424,14 +424,16 @@ oop newLambda(oop parameters, oop body)
return obj;
}
oop newClosure(oop lambda, oop environment)
oop newClosure(oop function, oop environment)
{
oop obj = make(Closure);
_set(obj, Closure,lambda, lambda);
_set(obj, Closure,function, function);
_set(obj, Closure,environment, environment);
return obj;
}
int isClosure(oop obj) { return is(Closure, obj); }
#endif
oop macros = 0;
@ -530,36 +532,40 @@ char *storeString(oop obj, int indent);
oop Object_get(oop obj, oop key)
{
oop o = obj;
while (is(Object, o)) {
ssize_t ind = Object_find(o, key);
if (ind >= 0) return _get(o, Object,properties)[ind].val;
o = _getDelegate(o);
}
# define makeCase(NAME) case NAME: o = p##NAME; break;
oop o;
switch (getType(obj)) {
doTypes(makeCase);
case Object: break;
case Undefined: o = pUndefined; break;
case Integer: o = pInteger; break;
case Float: o = pFloat; break;
case String: o = pString; break;
case Symbol: o = pSymbol; break;
case Primitive: o = pPrimitive; break;
# if PRIMCLOSURE
case Lambda:
if (key == sym_parameters) return _get(obj, Lambda,parameters);
if (key == sym_body ) return _get(obj, Lambda,body );
o = pLambda;
break;
case Closure:
if (key == sym_function ) return _get(obj, Closure,function );
if (key == sym_environment) return _get(obj, Closure,environment);
if (key == sym_fixed ) return _get(obj, Closure,fixed) ? sym_t : nil;
o = pClosure;
break;
# endif
case Object: {
ssize_t ind = Object_find(obj, key);
if (ind >= 0) return _get(obj, Object,properties)[ind].val;
o = _getDelegate(obj);
break;
}
}
# undef makeCase
# if !DELOPT
if (key == prop_delegate) return o; // implicit delegate of atomic object
# endif
if (key == prop_delegate) return o;
while (is(Object, o)) {
ssize_t ind = Object_find(o, key);
if (ind >= 0) return _get(o, Object,properties)[ind].val;
o = _getDelegate(o);
}
# if DELOPT
if (key == prop_delegate) {
# define makeCase(NAME) case NAME: return p##NAME;
switch (getType(obj)) {
doTypes(makeCase);
case Object: return _getDelegate(obj);
}
# undef makeCase
}
# endif
fatal("%s.%s is undefined", storeString(obj, 0), storeString(key, 0));
return nil;
}
@ -586,6 +592,20 @@ oop setvar(oop obj, oop key, oop val)
oop Object_put(oop obj, oop key, oop val)
{
# if PRIMCLOSURE
switch (getType(obj)) {
case Lambda:
if (key == sym_parameters ) { _set(obj, Lambda,parameters, val); return val; }
if (key == sym_body ) { _set(obj, Lambda,body, val); return val; }
break;
case Closure:
if (key == sym_fixed ) { _set(obj, Closure,fixed, nil != val); return val; }
if (key == sym_function ) { _set(obj, Closure,function, val); return val; }
if (key == sym_environment) { _set(obj, Closure,environment, val); return val; }
default:
break;
}
# endif
ssize_t ind = Object_find(obj, key);
struct property *kvs = _get(obj, Object,properties);
if (ind < 0) {
@ -723,8 +743,37 @@ oop printOn(oop buf, oop obj, int indent)
break;
}
#if PRIMCLOSURE
case Lambda: String_appendAll(buf, "<lambda>"); break;
case Closure: String_appendAll(buf, "<closure>"); break;
case Lambda: {
String_appendAll(buf, "<<Lambda>>");
if (!indent) break;
String_append(buf, '\n');
for (int j = indent; j--;) String_appendAll(buf, " | ");
String_appendAll(buf, " body: ");
printOn(buf, _get(obj, Lambda,body), indent+1);
String_append(buf, '\n');
for (int j = indent; j--;) String_appendAll(buf, " | ");
String_appendAll(buf, " parameters: ");
printOn(buf, _get(obj, Lambda,parameters), indent+1);
break;
}
case Closure: {
String_appendAll(buf, "<<Closure>>");
if (!indent) break;
String_append(buf, '\n');
for (int j = indent; j--;) String_appendAll(buf, " | ");
String_appendAll(buf, " environment: ");
printOn(buf, _get(obj, Closure,environment), indent+1);
String_append(buf, '\n');
for (int j = indent; j--;) String_appendAll(buf, " | ");
String_appendAll(buf, " function: ");
printOn(buf, _get(obj, Closure,function), indent+1);
break;
break;
}
#endif
case Object: {
int level = 0;
@ -1144,7 +1193,11 @@ oop newApply(oop function, oop arguments)
int isFixed(oop func)
{
# if PRIMCLOSURE
return is(Closure, func) && _get(func, Closure,fixed);
# else
return Object_getLocal(func, sym_fixed) != nil;
# endif
}
oop Call_eval(oop exp, oop env)
@ -1220,6 +1273,19 @@ oop newLambda(oop parameters, oop body)
return o;
}
oop newClosure(oop function, oop environment)
{
oop o = new(pClosure);
Object_put(o, sym_function , function );
Object_put(o, sym_environment, environment);
return o;
}
int isClosure(oop obj)
{
return is(Object, obj) && pClosure == _getDelegate(obj);
}
oop Lambda_eval(oop exp, oop env)
{
return newClosure(exp, env);
@ -1231,14 +1297,6 @@ void Lambda_codeOn(oop exp, oop str, oop env)
codeBlockOn(str, Object_get(exp, sym_body));
}
oop newClosure(oop lambda, oop environment)
{
oop o = new(pClosure);
Object_put(o, sym_lambda , lambda );
Object_put(o, sym_environment, environment);
return o;
}
oop Closure_eval(oop exp, oop env)
{
return exp;
@ -1445,9 +1503,10 @@ oop quasiclone(oop exp, oop env)
struct property *kvs = _get(exp, Object,properties);
int psize = _get(exp, Object,psize);
for (int i = 0; i < psize; ++i)
Object_put(clone, kvs[i].key, quasiclone(kvs[i].val, env));
if (kvs[i].key != prop_delegate)
Object_put(clone, kvs[i].key, quasiclone(kvs[i].val, env));
oop delegate = _getDelegate(exp);
if (nil != delegate)
if (nil != delegate) // always shallow copied
Object_put(clone, prop_delegate, delegate);
return clone;
}
@ -2031,14 +2090,14 @@ oop apply(oop func, oop self, oop args, oop env)
#if PRIMCLOSURE
if (Closure != functype)
fatal("cannot %s %s", (nil == self ? "call" : "invoke"), storeString(func, 0));
oop lambda = _get(func, Closure,lambda);
oop lambda = _get(func, Closure,function);
oop environment = _get(func, Closure,environment);
oop parameters = _get(lambda, Lambda,parameters);
oop body = _get(lambda, Lambda,body);
#else
if (Object != functype || pClosure != _getDelegate(func))
fatal("cannot %s %s", (nil == self ? "call" : "invoke"), storeString(func, 0));
oop lambda = Object_get(func, sym_lambda);
oop lambda = Object_get(func, sym_function);
oop environment = Object_get(func, sym_environment);
oop parameters = Object_get(lambda, sym_parameters);
oop body = Object_get(lambda, sym_body);
@ -2091,20 +2150,22 @@ enum typecode getTypecode(oop exp)
return NAME##_eval(exp, env); \
}
doProtos(defineEval)
#undef defineEval
#endif // !TYPECODES
#define defineCodeOn(NAME) \
static inline oop prim_##NAME##_codeOn(oop func, oop exp, oop args, oop env) { \
NAME##_codeOn(exp, getArgType(args, 0, String, #NAME".codeOn"), env); \
return exp; \
} \
doProtos(defineEval)
doProtos(defineCodeOn)
#undef defineEval
#undef defineCodeOn
#endif // !TYPECODES
static inline oop evalobj(oop exp, oop env)
{
# if !TYPECODES
@ -2117,7 +2178,7 @@ static inline oop evalobj(oop exp, oop env)
enum typecode type = getTypecode(exp);
# define defineEval(NAME) case t##NAME: NAME##_eval(exp, env); break;
# define defineEval(NAME) case t##NAME: return NAME##_eval(exp, env);
switch (type) {
doProtos(defineEval);
}
@ -2196,13 +2257,31 @@ oop prim_length(oop func, oop self, oop args, oop env)
oop prim_keys(oop func, oop self, oop args, oop env)
{
oop keys = new(pObject);
if (is(Object, self)) {
int size = _get(self, Object,psize);
struct property *kvs = _get(self, Object,properties);
# if DELOPT
if (nil != _getDelegate(self)) Object_push(keys, prop_delegate);
# if DELOPT
if (nil != _getDelegate(self)) Object_push(keys, prop_delegate);
# endif
switch (getType(self)) {
case Undefined: case Integer: case Float: case String: case Symbol: case Primitive:
break;
case Object: {
int size = _get(self, Object,psize);
struct property *kvs = _get(self, Object,properties);
for (int i = 0; i < size; ++i) Object_push(keys, kvs[i].key);
break;
}
# if PRIMCLOSURE
case Lambda: {
Object_push(keys, sym_parameters);
Object_push(keys, sym_body);
break;
}
case Closure: {
Object_push(keys, sym_fixed);
Object_push(keys, sym_lambda);
Object_push(keys, sym_environment);
break;
}
# endif
for (int i = 0; i < size; ++i) Object_push(keys, kvs[i].key);
}
return keys;
}
@ -2219,21 +2298,8 @@ oop prim_makeForm(oop func, oop self, oop args, oop env)
oop result = nil;
for (int i = 0; i < argc; ++i) {
result = indexed[i];
if (!is(Closure, result)) fatal("makeForm: argument must be closure");
_set(result, Closure,fixed, 1);
}
return result;
}
oop prim_makeMacro(oop func, oop self, oop args, oop env)
{
int argc = _get(args, Object,isize);
oop *indexed = _get(args, Object,indexed);
oop result = nil;
for (int i = 0; i < argc; ++i) {
result = indexed[i];
if (!is(Closure, result)) fatal("makeForm: argument must be closure");
_set(result, Closure,fixed, 1);
if (!isClosure(result)) fatal("makeForm: argument must be closure");
Object_put(result, sym_fixed, sym_t);
}
return result;
}
@ -2439,11 +2505,16 @@ int main(int argc, char **argv)
# undef defineProto
#if TYPECODES
Object_put(pObject, prop_eval, newPrimitive(prim_env)); // inherited by all objects
# define defineEvaluator(NAME) \
_set(intern(#NAME), Symbol,typecode, t##NAME);
#else // !TYPECODES
# define defineEvaluator(NAME) \
Object_put(p##NAME, prop_eval, newPrimitive(prim_##NAME##_eval));
#endif // !TYPECODES
doProtos(defineEvaluator);

Caricamento…
Annulla
Salva