Skip to content

Commit

Permalink
macro-like behaviour feom lazy functions
Browse files Browse the repository at this point in the history
  • Loading branch information
billhails committed Oct 27, 2024
1 parent 48dd467 commit 3ba59a7
Show file tree
Hide file tree
Showing 12 changed files with 281 additions and 301 deletions.
6 changes: 0 additions & 6 deletions src/ast.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ structs:
symbol: HashSymbol
expression: AstExpression

AstGensymDefine:
basename: HashSymbol
expression: AstExpression

AstAlias:
name: HashSymbol
type: AstType
Expand Down Expand Up @@ -194,7 +190,6 @@ unions:

AstDefinition:
define: AstDefine
gensymDefine: AstGensymDefine
typeDef: AstTypeDef
macro: AstDefMacro
alias: AstAlias
Expand Down Expand Up @@ -225,7 +220,6 @@ unions:
funCall: AstFunCall
lookup: AstLookup
symbol: HashSymbol
gensym: HashSymbol
number: MaybeBigInt
character: character
fun: AstCompositeFunction
Expand Down
13 changes: 3 additions & 10 deletions src/lambda.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ structs:
args: LamVarList
exp: LamExp

LamMacro:
args: LamVarList
exp: LamExp
env: LamContext

LamVarList:
var: HashSymbol
next: LamVarList
Expand Down Expand Up @@ -141,7 +136,6 @@ structs:

LamLetRecBindings:
var: HashSymbol
isGenSym: bool
val: LamExp
next: LamLetRecBindings

Expand Down Expand Up @@ -240,7 +234,6 @@ unions:
namespaces: LamNamespaceArray
lam: LamLam
var: HashSymbol
gensym: HashSymbol
stdint: int
biginteger: MaybeBigInt
prim: LamPrimApp
Expand Down Expand Up @@ -294,10 +287,10 @@ unions:

hashes:
LamMacroTable:
entries: LamMacro
entries: void_ptr

LamGenSymTable:
entries: HashSymbol
LamMacroArgsTable:
entries: void_ptr

LamInfoTable:
entries: LamInfo
Expand Down
176 changes: 84 additions & 92 deletions src/lambda_conversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ static LamList *convertExpressions(AstExpressions *, LamContext *);
static LamSequence *convertSequence(AstExpressions *, LamContext *);
static LamLetRecBindings *prependDefinition(AstDefinition *, LamContext *, LamLetRecBindings *);
static LamLetRecBindings *prependDefine(AstDefine *, LamContext *, LamLetRecBindings *);
static LamLetRecBindings *prependGensymDefine(AstGensymDefine *, LamContext *, LamLetRecBindings *);
static LamExp *convertExpression(AstExpression *, LamContext *);
static bool typeHasFields(AstTypeBody *);
static LamTypeDefList *collectTypeDefs(AstDefinitions *, LamContext *);
static void collectAliases(AstDefinitions *, LamContext *);
static void collectMacros(AstDefinitions *, LamContext *);
static LamTypeConstructor *collectTypeConstructor(AstTypeConstructor *, LamType *, int, int, bool, LamContext *);
static void collectTypeInfo(HashSymbol *, AstTypeConstructorArgs *, LamTypeConstructor *, bool, int, int, int, LamContext *);
static LamTypeConstructorArgs *convertAstTypeList(AstTypeList *, LamContext *);
Expand Down Expand Up @@ -135,7 +133,6 @@ static LamExp *lamConvert(AstDefinitions *definitions,
collectAliases(definitions, env);
LamTypeDefList *typeDefList = collectTypeDefs(definitions, env);
int save = PROTECT(typeDefList);
collectMacros(definitions, env);
LamLetRecBindings *funcDefsList = convertFuncDefs(definitions, env);
PROTECT(funcDefsList);
funcDefsList = makePrintFunctions(typeDefList, funcDefsList, env, inPreamble);
Expand Down Expand Up @@ -240,13 +237,19 @@ static LamExp *lamConvertLookup(AstLookup *lookup, LamContext *env) {
return res;
}

static LamLetRecBindings *convertFuncDefs(AstDefinitions *definitions,
LamContext *env) {
static void checkMacro(AstDefinition *definition, LamContext *env) {
if (definition->type == AST_DEFINITION_TYPE_MACRO) {
setLamMacroTable(env->macros, definition->val.macro->name, NULL);
}
}

static LamLetRecBindings *convertFuncDefs(AstDefinitions *definitions, LamContext *env) {
ENTER(convertFuncDefs);
if (definitions == NULL) {
LEAVE(convertFuncDefs);
return NULL;
}
checkMacro(definitions->definition, env);
LamLetRecBindings *next = convertFuncDefs(definitions->next, env);
int save = PROTECT(next);
LamLetRecBindings *this =
Expand Down Expand Up @@ -552,7 +555,6 @@ static void collectAliases(AstDefinitions *definitions, LamContext *env) {
}
switch (definitions->definition->type) {
case AST_DEFINITION_TYPE_DEFINE:
case AST_DEFINITION_TYPE_GENSYMDEFINE:
case AST_DEFINITION_TYPE_BLANK:
case AST_DEFINITION_TYPE_TYPEDEF:
case AST_DEFINITION_TYPE_MACRO:
Expand Down Expand Up @@ -605,55 +607,42 @@ static LamVarList *collectMacroArgs(AstArgList *argList) {
return this;
}

static LamMacro *convertAstMacro(AstAltFunction *astMacro, LamContext *env) {
static void populateArgsTable(LamMacroArgsTable *symbols, LamVarList *args) {
if (args == NULL) return;
setLamMacroArgsTable(symbols, args->var, NULL);
populateArgsTable(symbols, args->next);
}

static LamExp *convertAstMacro(AstDefMacro *astMacro, LamContext *env) {
ENTER(convertAstMacro);
LamVarList *args = collectMacroArgs(astMacro->altArgs->argList);
// ParserInfo PI = CPI(astMacro);
// eprintf("convert macro %s +%d %s\n", astMacro->name->name, PI.lineno, PI.filename);
LamVarList *args = collectMacroArgs(astMacro->definition->altArgs->argList);
int save = PROTECT(args);
LamExp *body = convertNest(astMacro->nest, env);
LamExp *body = convertNest(astMacro->definition->nest, env);
PROTECT(body);
LamMacro *res = newLamMacro(CPI(astMacro), args, body, env);
LamMacroArgsTable *symbols = newLamMacroArgsTable();
PROTECT(symbols);
populateArgsTable(symbols, args);
body = lamPerformMacroSubstitutions(body, symbols);
PROTECT(body);
LamLam *lam = newLamLam(CPI(astMacro), args, body);
PROTECT(lam);
LamExp *res = newLamExp_Lam(CPI(lam), lam);
PROTECT(res);
setLamMacroTable(env->macros, astMacro->name, NULL);
LEAVE(convertAstMacro);
UNPROTECT(save);
return res;
}

static void collectMacro(AstDefMacro *astMacro, LamContext *env) {
ENTER(collectMacro);
DEBUG("collectMacro %s", astMacro->name->name);
LamMacro *lamMacro = convertAstMacro(astMacro->definition, env);
int save = PROTECT(lamMacro);
setLamMacroTable(env->macros, astMacro->name, lamMacro);
LEAVE(collectMacro);
UNPROTECT(save);
}

static void collectMacros(AstDefinitions *definitions, LamContext *env) {
if (definitions == NULL) {
return;
}
switch (definitions->definition->type) {
case AST_DEFINITION_TYPE_DEFINE:
case AST_DEFINITION_TYPE_GENSYMDEFINE:
case AST_DEFINITION_TYPE_BLANK:
case AST_DEFINITION_TYPE_TYPEDEF:
case AST_DEFINITION_TYPE_ALIAS:
break;
case AST_DEFINITION_TYPE_MACRO:
collectMacro(definitions->definition->val.macro, env);
break;
default:
cant_happen("unrecognised %s", astDefinitionTypeName(definitions->definition->type));
}
collectMacros(definitions->next, env);
}

static LamTypeDefList *collectTypeDefs(AstDefinitions *definitions, LamContext *env) {
if (definitions == NULL) {
return NULL;
}
switch (definitions->definition->type) {
case AST_DEFINITION_TYPE_DEFINE:
case AST_DEFINITION_TYPE_GENSYMDEFINE:
case AST_DEFINITION_TYPE_ALIAS:
case AST_DEFINITION_TYPE_BLANK:
case AST_DEFINITION_TYPE_MACRO:
Expand All @@ -672,6 +661,18 @@ static LamTypeDefList *collectTypeDefs(AstDefinitions *definitions, LamContext *
}
}

static LamLetRecBindings *prependMacro(AstDefMacro * macro, LamContext * env,
LamLetRecBindings * next) {
ENTER(prependMacro);
LamExp *exp = convertAstMacro(macro, env);
int save = PROTECT(exp);
LamLetRecBindings *this =
newLamLetRecBindings(CPI(macro), dollarSubstitute(macro->name, CPI(macro)), exp, next);
UNPROTECT(save);
LEAVE(prependMacro);
return this;
}

static LamLetRecBindings *prependDefinition(AstDefinition *definition,
LamContext *env,
LamLetRecBindings *next) {
Expand All @@ -681,13 +682,12 @@ static LamLetRecBindings *prependDefinition(AstDefinition *definition,
case AST_DEFINITION_TYPE_DEFINE:
result = prependDefine(definition->val.define, env, next);
break;
case AST_DEFINITION_TYPE_GENSYMDEFINE:
result = prependGensymDefine(definition->val.gensymDefine, env, next);
case AST_DEFINITION_TYPE_MACRO:
result = prependMacro(definition->val.macro, env, next);
break;
case AST_DEFINITION_TYPE_ALIAS:
case AST_DEFINITION_TYPE_TYPEDEF:
case AST_DEFINITION_TYPE_BLANK:
case AST_DEFINITION_TYPE_MACRO:
result = next;
break;
default:
Expand Down Expand Up @@ -727,24 +727,12 @@ static LamLetRecBindings *prependDefine(AstDefine * define, LamContext * env,
tpmc_mermaid_flag = 0;
int save = PROTECT(exp);
LamLetRecBindings *this =
newLamLetRecBindings(CPI(define), dollarSubstitute(define->symbol, CPI(define)), false, exp, next);
newLamLetRecBindings(CPI(define), dollarSubstitute(define->symbol, CPI(define)), exp, next);
UNPROTECT(save);
LEAVE(prependDefine);
return this;
}

static LamLetRecBindings *prependGensymDefine(AstGensymDefine * define, LamContext * env,
LamLetRecBindings * next) {
ENTER(prependGensymDefine);
LamExp *exp = convertExpression(define->expression, env);
int save = PROTECT(exp);
LamLetRecBindings *this =
newLamLetRecBindings(CPI(define), define->basename, true, exp, next);
UNPROTECT(save);
LEAVE(prependGensymDefine);
return this;
}

static HashSymbol *dollarSubstitute(HashSymbol *symbol, ParserInfo I __attribute__((unused))) {
if (!inPreamble) {
// eprintf("dollarSubstitute %s not in preamble\n", symbol->name);
Expand Down Expand Up @@ -822,47 +810,55 @@ static LamExp *makeUnaryNeg(LamList *args) {
return result;
}

static LamMacro *getMacro(HashSymbol *symbol, LamContext *env) {
if (env == NULL) return NULL;
LamMacro *result = NULL;
if (getLamMacroTable(env->macros, symbol, &result)) {
return result;
static bool isMacro(ParserInfo PI __attribute__((unused)), HashSymbol *symbol, LamContext *env) {
if (env == NULL) {
// eprintf("ismacro %s false +%d, %s\n", symbol->name, PI.lineno, PI.filename);
return false;
}
return getMacro(symbol, env->parent);
if (getLamMacroTable(env->macros, symbol, NULL)) {
// eprintf("ismacro %s true +%d, %s\n", symbol->name, PI.lineno, PI.filename);
return true;
}
return isMacro(PI, symbol, env->parent);
}

static void bindMacroArgs(LamExpTable *table, LamVarList *fargs, LamList *aargs) {
while (fargs && aargs) {
setLamExpTable(table, fargs->var, aargs->exp);
fargs = fargs->next;
aargs = aargs->next;
}
static LamExp *thunkMacroArg(LamExp *arg) {
LamLam *lambda = newLamLam(CPI(arg), NULL, arg);
int save = PROTECT(lambda);
LamExp *res = newLamExp_Lam(CPI(lambda), lambda);
UNPROTECT(save);
return res;
}

static LamExp *expandMacro(HashSymbol *name, LamMacro *macro, LamList *args) {
if (countLamList(args) != countLamVarList(macro->args)) {
conversionError(CPI(args), "wrong number of arguments to macro %s", name->name);
return newLamExp_Error(CPI(args));
}
if (countLamList(args) == 0) {
return macro->exp;
static LamList *wrapMacroArgs(LamList *args) {
if (args == NULL) {
return NULL;
}
LamExpTable *table = newLamExpTable();
int save = PROTECT(table);
bindMacroArgs(table, macro->args, args);
LamGenSymTable *gensyms = newLamGenSymTable();
PROTECT(gensyms);
LamExp *res = copyLamExp(macro->exp);
PROTECT(res);
res = lamPerformMacroSubstitutions(res, table, gensyms);
LamList *next = wrapMacroArgs(args->next);
int save = PROTECT(next);
LamExp *arg = thunkMacroArg(args->exp);
PROTECT(arg);
LamList *this = newLamList(CPI(arg), arg, next);
UNPROTECT(save);
return this;
}

// wrap each argument to the macro in a thunk, the macro will invoke
static LamExp *wrapMacro(ParserInfo PI, HashSymbol *symbol, LamList *args) {
args = wrapMacroArgs(args);
int save = PROTECT(args);
LamExp *macro = newLamExp_Var(PI, symbol);
PROTECT(macro);
LamApply *apply = newLamApply(PI, macro, args);
PROTECT(apply);
LamExp *res = newLamExp_Apply(PI, apply);
UNPROTECT(save);
return res;
}

static LamExp *makePrimApp(HashSymbol *symbol, LamList *args, LamContext *env) {
LamMacro *macro = getMacro(symbol, env);
if (macro != NULL) {
return expandMacro(symbol, macro, args);
static LamExp *makePrimApp(ParserInfo PI, HashSymbol *symbol, LamList *args, LamContext *env) {
if (isMacro(PI, symbol, env)) {
return wrapMacro(PI, symbol, args);
}
if (symbol == negSymbol())
return makeUnaryNeg(args);
Expand Down Expand Up @@ -1136,7 +1132,7 @@ static LamExp *convertFunCall(AstFunCall *funCall, LamContext *env) {
switch (findUnderlyingType(function)) {
case LAMEXP_TYPE_VAR:{
LamExp *symbol = findUnderlyingValue(function);
result = makePrimApp(symbol->val.var, args, env);
result = makePrimApp(CPI(funCall), symbol->val.var, args, env);
if (result != NULL) {
UNPROTECT(save);
return result;
Expand Down Expand Up @@ -1363,10 +1359,6 @@ static LamExp *convertExpression(AstExpression *expression, LamContext *env) {
ENTER(convertExpression);
LamExp *result = NULL;
switch (expression->type) {
case AST_EXPRESSION_TYPE_GENSYM:
DEBUG("gensym");
result = newLamExp_Gensym(CPI(expression), expression->val.gensym);
break;
case AST_EXPRESSION_TYPE_BACK:
DEBUG("back");
result = newLamExp_Back(CPI(expression));
Expand Down
6 changes: 2 additions & 4 deletions src/lambda_substitution.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ static HashSymbol *performVarSubstitutions(HashSymbol *var, TpmcSubstitutionTabl

static void substError(ParserInfo PI, const char *message, ...) __attribute__((format(printf, 2, 3)));

static void substError(ParserInfo PI, const char *message, ...) __attribute__((unused));

static void substError(ParserInfo PI, const char *message, ...) {
va_list args;
va_start(args, message);
Expand Down Expand Up @@ -432,10 +434,6 @@ LamExp *lamPerformSubstitutions(LamExp *exp,
case LAMEXP_TYPE_LOOKUP:
exp->val.lookup = performLookupSubstitutions(exp->val.lookup, substitutions);
break;
case LAMEXP_TYPE_GENSYM:
substError(CPI(exp), "cannot use dollar-qualified variable outside of a macro");
exp->type = LAMEXP_TYPE_VAR;
break;
default:
cant_happen
("unrecognized LamExp type %s", lamExpTypeName(exp->type));
Expand Down
Loading

0 comments on commit 3ba59a7

Please sign in to comment.