Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/src/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 18.9.2025 mit Größe 32 kB image not shown  

Quelle  syntaxtree.c   Sprache: C

 
/****************************************************************************
**
**  This file is part of GAP, a system for computational discrete algebra.
**
**  Copyright of GAP belongs to its developers, whose names are too numerous
**  to list here. Please refer to the COPYRIGHT file for details.
**
**  SPDX-License-Identifier: GPL-2.0-or-later
*/


#include "syntaxtree.h"

#include "bool.h"
#include "calls.h"
#include "code.h"
#include "common.h"
#include "error.h"
#include "exprs.h"
#include "gvars.h"
#include "integer.h"
#include "lists.h"
#include "modules.h"
#include "opers.h"
#include "plist.h"
#include "precord.h"
#include "profile.h"
#include "records.h"
#include "stats.h"
#include "stringobj.h"
#include "vars.h"

#include <ctype.h>
#include <stdarg.h>

enum { MAX_ARITY = 4 };

typedef Obj (*CompileFuncT)(Obj node, Expr expr);
typedef Obj (*CompileArgT)(Expr expr);
typedef Expr (*CodeFuncT)(CodeState * cs, Obj node);
typedef Expr (*CodeArgT)(CodeState * cs, Obj node);


typedef struct {
    const Char * argname;
    CompileArgT  argcomp;
    CodeArgT     argcode;
    Int          isStat;
} ArgT;

typedef struct {
    UInt1        tnum;
    CompileFuncT compile;
    CodeFuncT    code;
    const Char * name;
    UInt         arity;
    ArgT         args[MAX_ARITY];
} CompilerT;

// We put compilers for statements and expressions into the same static array,
// assuming that the set of their respective ids are disjoint.
static const CompilerT Compilers[];
#define COMPILER_ARITY(...) (sizeof((ArgT[]){ __VA_ARGS__ }) / sizeof(ArgT))
#define COMPILER_GENERIC(tnum, compiler, coder, ...)                         \
    [tnum] = {                                                               \
        tnum,           compiler, coder, #tnum, COMPILER_ARITY(__VA_ARGS__), \
        { __VA_ARGS__ }                                                      \
    }

#define COMPILER(tnum, compiler, coder)                                      \
    COMPILER_GENERIC(tnum, compiler, coder)

#define COMPILER_(tnum, ...)                                                 \
    COMPILER_GENERIC(tnum, SyntaxTreeDefaultCompiler,                        \
                     SyntaxTreeDefaultCoder, __VA_ARGS__)

#define ARG(name, func, coder, isStat)                                       \
    {                                                                        \
        name, func, coder, isStat                                            \
    }

// ARG_EXPR indicates an "expression argument", i.e., that the corresponding
// slot of the statement or expression type it belongs to is meant to
// reference an expression. This information is used for validation when
// coding an AST back into a T_BODY object. The expression is stored in resp.
// read from the record entry <name>.
#define ARG_EXPR(name, func, coder) ARG(name, func, coder, 0)

// ARG_STAT is like ARG_EXPR, except that it indicates that the corresponding
// slot should contain a statement instead of an expression. There is no
// ARG_STAT, because it is never used.


// ARG_EXPR_ can be used instead of ARG_EXPR if the default compiler
// and coder should be used to compile the corresponding expression or code
// the corresponding subnode.
#define ARG_EXPR_(name)                                                      \
    ARG(name, SyntaxTreeCompiler, SyntaxTreeDefaultExprCoder, 0)
#define ARG_STAT_(name)                                                      \
    ARG(name, SyntaxTreeCompiler, SyntaxTreeDefaultStatCoder, 1)

// ARGS_EXPR can be used instead of ARG_EXPR as the last argument to the
// COMPILER_ macro, and indicates that a variable number of arguments follow;
// all are supposed to be expressions; and all of them are to be stored into a
// plist which is stored in resp. read from the record entry <name>.
#define ARGS_EXPR(name) ARG(name, 0, 0, 0)
#define ARGS_STAT(name) ARG(name, 0, 0, 1)

// plain list mapping statement tnums to strings
// like "EXPR_INT"
static Obj typeStrings;

// plain record mapping strings like "EXPR_INT" to the
// corresponding statement tnum
static Obj typeRec;


static Obj ElmRecST(UInt1 tnum, Obj node, const char * name)
{
    RequirePlainRec("ElmRecST", node);
    UInt rnam = RNamName(name);
    if (!IsbPRec(node, rnam)) {
        const char * typename = Compilers[tnum].name;
        ErrorQuit("while coding %s: node field <%s> must be present",
                  (Inttypename, (Int)name);
    }
    return ElmPRec(node, rnam);
}

static Obj SyntaxTreeFunc(Obj result, Obj func);

static UInt1 FIND_TNUM_FROM_STRING(Obj typestr)
{
    UInt rnam = RNamObj(typestr);
    if (IsbPRec(typeRec, rnam)) {
        return (UInt1)UInt_ObjInt(ElmPRec(typeRec, rnam));
    }
    ErrorQuit("Unrecognized syntax tree node type %g", (Int)typestr, 0);
}

static UInt1 GetTypeTNum(Obj node)
{
    RequirePlainRec("GetTypeTNum", node);
    UInt type = RNamName("type");
    if (!IsbPRec(node, type)) {
        ErrorQuit("while coding: field is not present", 0, 0);
    }
    return FIND_TNUM_FROM_STRING(ElmPRec(node, type));
}

static inline Obj NewSyntaxTreeNode(UInt1 tnum)
{
    Obj result;
    Obj typestr;

    typestr = ELM_LIST(typeStrings, tnum + 1);
    result = NEW_PREC(2);
    AssPRec(result, RNamName("type"), typestr);

    return result;
}

static Obj SyntaxTreeCompiler(Expr expr)
{
    Obj       result;
    UInt1     tnum;
    CompilerT comp;

    // TODO: GAP_ASSERT
    tnum = TNUM_EXPR(expr);
    comp = Compilers[tnum];

    result = NewSyntaxTreeNode(comp.tnum);

    return comp.compile(result, expr);
}

static Obj SyntaxTreeRNam(Expr expr)
{
    return NAME_RNAM(expr);
}

static Expr SyntaxTreeCodeRNamObj(CodeState * cs, Obj node)
{
    return RNamObj(node);
}


static Obj SyntaxTreeDefaultCompiler(Obj result, Expr expr)
{
    int       i;
    UInt1     tnum;
    CompilerT comp;
    BOOL      didvariadic = 0;
    Int       offset = 0;

    // TODO: GAP_ASSERT tnum range
    tnum = TNUM_EXPR(expr);
    comp = Compilers[tnum];

    for (i = 0; i < comp.arity; i++) {
        UInt rnam = RNamName(comp.args[i].argname);
        Obj  compiled;

        if (comp.args[i].argcomp) {
            Expr subexpr = READ_EXPR(expr, i + offset);
            compiled = comp.args[i].argcomp(subexpr);
        }
        else {
            // special case: one argument may have zero as decompiler,
            // which expresses that this slot is "variadic", and
            // is decompiled into a single list
            GAP_ASSERT(!didvariadic);
            didvariadic = 1;
            // Avoid warning about used variable when not in debug mode
            (void)didvariadic;

            // compile the variadic part into a single list
            const UInt nr = SIZE_EXPR(expr) / sizeof(expr);
            const UInt varlength = nr - (comp.arity - 1);
            compiled = NEW_PLIST(T_PLIST, nr - (comp.arity - 1));
            for (; offset < varlength; offset++) {
                Expr subexpr = READ_EXPR(expr, i + offset);
                // handle 0 to properly deal with EXPR_LIST
                Obj obj = subexpr ? SyntaxTreeCompiler(subexpr) : 0;
                PushPlist(compiled, obj);
            }
            // offset gets set one bigger final time around loop
            offset--;
        }

        AssPRec(result, rnam, compiled);
    }

    GAP_ASSERT(i + offset == SIZE_EXPR(expr) / sizeof(expr));
    return result;
}

static Stat SyntaxTreeDefaultStatCoder(CodeState *, Obj);
static Stat SyntaxTreeDefaultExprCoder(CodeState *, Obj);

static Expr SyntaxTreeDefaultCoder(CodeState * cs, Obj node)
{

    RequirePlainRec("SyntaxTreeDefaultCoder", node);

    UInt1 tnum = GetTypeTNum(node);

    CompilerT comp = Compilers[tnum];

    if (comp.code != SyntaxTreeDefaultCoder) {
        return comp.code(cs, node);
    }

    // compute how big the statement/expression we are generating needs to
    // be, i.e., how many Obj-sized "slots" we need; this is usually
    // comp.arity, but we need to take into account variadic argument lists
    UInt slots = comp.arity;
    UInt arity = comp.arity;

    Int varargloc = -1;
    for (UInt i = 0; i < comp.arity; ++i) {
        if (comp.args[i].argcomp == 0) {
            GAP_ASSERT(varargloc == -1);
            varargloc = i;
        }
    }

    Obj vararglist = 0;

    if (varargloc != -1) {
        vararglist = ElmRecST(tnum, node, comp.args[varargloc].argname);
        slots = arity - 1 + LEN_LIST(vararglist);
    }

    // reserve space for the statement or expressions
    Expr expr = NewStatOrExpr(cs, tnum, slots * sizeof(Expr), 0);

    Int  i;
    UInt offset = 0;

    for (i = 0; i < arity; i++) {
        if (i == varargloc) {
            for (; offset < LEN_LIST(vararglist); offset++) {
                Obj elem = ELM0_LIST(vararglist, offset + 1);
                // Deal with empty entries in list expressions
                if (elem == 0) {
                    WRITE_EXPR(cs, expr, i + offset, 0);
                }
                else if (comp.args[i].isStat) {
                    WRITE_EXPR(cs, expr, i + offset,
                               SyntaxTreeDefaultStatCoder(cs, elem));
                }
                else {
                    WRITE_EXPR(cs, expr, i + offset,
                               SyntaxTreeDefaultExprCoder(cs, elem));
                }
            }
            // offset gets set one bigger final time around loop
            offset--;
        }
        else {
            Obj subast = ElmRecST(tnum, node, comp.args[i].argname);
            WRITE_EXPR(cs, expr, i + offset,
                       comp.args[i].argcode(cs, subast));
        }
    }

    return expr;
}


// Checks if node codes a statement
static Stat SyntaxTreeDefaultStatCoder(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeDefaultStatCoder", node);
    Int tnum = GetTypeTNum(node);
    if (!(FIRST_STAT_TNUM <= tnum && tnum <= LAST_STAT_TNUM))
        ErrorQuit("tried to code expression %s as statement",
                  (Int)Compilers[tnum].name, 0);
    return (Stat)SyntaxTreeDefaultCoder(cs, node);
}

// Checks if node codes an expression
static Expr SyntaxTreeDefaultExprCoder(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeDefaultExprCoder", node);
    UInt1 tnum = GetTypeTNum(node);
    if (!(FIRST_EXPR_TNUM <= tnum && tnum <= LAST_EXPR_TNUM))
        ErrorQuit("tried to code statement %s as expression",
                  (Int)Compilers[tnum].name, 0);
    return (Expr)SyntaxTreeDefaultCoder(cs, node);
}

static Expr SyntaxTreeCodeGVar(CodeState * cs, Obj name)
{
    RequireStringRep("SyntaxTreeCodeGVar", name);
    return GVarName(CONST_CSTR_STRING(name));
}

static Obj SyntaxTreeRefLVar(Obj result, Expr expr)
{
    AssPRec(result, RNamName("lvar"), INTOBJ_INT(LVAR_REF_LVAR(expr)));
    return result;
}

static Expr SyntaxTreeCodeRefLVar(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeRefLVar", node);
    Obj lvar = ElmRecST(EXPR_REF_LVAR, node, "lvar");
    RequireSmallInt("SyntaxTreeCodeRefLVar", lvar);
    return REF_LVAR_LVAR(INT_INTOBJ(lvar));
}

static Expr SyntaxTreeCodeObjInt(CodeState * cs, Obj node)
{
    return UInt_ObjInt(node);
}

static Obj SyntaxTreeEvalCompiler(Obj result, Expr expr)
{
    pauseProfiling();
    Obj o = EVAL_EXPR(expr);
    unpauseProfiling();
    AssPRec(result, RNamName("value"), o);
    return result;
}

static Obj SyntaxTreeFuncExpr(Obj result, Expr expr)
{
    Obj fexp = GET_VALUE_FROM_CURRENT_BODY(READ_EXPR(expr, 0));

    SyntaxTreeFunc(result, fexp);

    return result;
}

static Obj SyntaxTreeRangeExpr(Obj result, Expr expr)
{
    Obj first;
    Obj second;
    Obj last;

    if (SIZE_EXPR(expr) == 2 * sizeof(Expr)) {
        first = SyntaxTreeCompiler(READ_EXPR(expr, 0));
        last = SyntaxTreeCompiler(READ_EXPR(expr, 1));

        AssPRec(result, RNamName("first"), first);
        AssPRec(result, RNamName("last"), last);
    }
    else {
        first = SyntaxTreeCompiler(READ_EXPR(expr, 0));
        second = SyntaxTreeCompiler(READ_EXPR(expr, 1));
        last = SyntaxTreeCompiler(READ_EXPR(expr, 2));

        AssPRec(result, RNamName("first"), first);
        AssPRec(result, RNamName("second"), second);
        AssPRec(result, RNamName("last"), last);
    }

    return result;
}

static Expr SyntaxTreeCodeRangeExpr(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeRangeExpr", node);
    UInt hassecond = ISB_REC(node, RNamName("second"));
    UInt size = hassecond ? 3 : 2;
    Expr result = NewStatOrExpr(cs, EXPR_RANGE, size * sizeof(Expr), 0);
    WRITE_EXPR(
        cs, result, 0,
        SyntaxTreeDefaultExprCoder(cs, ElmRecST(EXPR_RANGE, node, "first")));
    WRITE_EXPR(
        cs, result, size - 1,
        SyntaxTreeDefaultExprCoder(cs, ElmRecST(EXPR_RANGE, node, "last")));
    if (hassecond) {
        WRITE_EXPR(cs, result, 1,
                   SyntaxTreeDefaultExprCoder(
                       cs, ElmRecST(EXPR_RANGE, node, "second")));
    }
    return result;
}

static Obj SyntaxTreeRecExpr(Obj result, Expr expr)
{
    Obj  key;
    Obj  val;
    Obj  list;
    Obj  subrec;
    Expr tmp;
    Int  i, len;

    len = SIZE_EXPR(expr) / (2 * sizeof(Expr));
    list = NEW_PLIST(T_PLIST, len);

    for (i = 1; i <= len; i++) {
        tmp = READ_EXPR(expr, 2 * i - 2);
        GAP_ASSERT(tmp != 0);

        subrec = NEW_PREC(2);
        PushPlist(list, subrec);

        if (IS_INTEXPR(tmp)) {
            key = NAME_RNAM((UInt)INT_INTEXPR(tmp));
        }
        else {
            key = SyntaxTreeCompiler(tmp);
        }
        AssPRec(subrec, RNamName("key"), key);

        tmp = READ_EXPR(expr, 2 * i - 1);
        val = SyntaxTreeCompiler(tmp);
        AssPRec(subrec, RNamName("value"), val);
    }
    AssPRec(result, RNamName("keyvalue"), list);

    return result;
}

static Expr SyntaxTreeCodeRecExpr(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeRecExpr", node);
    UInt1 tnum = GetTypeTNum(node);
    Obj   keyvalue = ElmRecST(tnum, node, "keyvalue");
    UInt  len = LEN_LIST(keyvalue);
    Expr  record = NewStatOrExpr(cs, tnum, 2 * len * sizeof(Expr), 0);
    for (int i = 0; i < len; i++) {
        Obj  keyvaluepair = ELM_LIST(keyvalue, i + 1);
        Obj  keynode = ElmRecST(tnum, keyvaluepair, "key");
        Obj  valuenode = ElmRecST(tnum, keyvaluepair, "value");
        Expr key;
        if (IS_STRING(keynode)) {
            key = INTEXPR_INT(RNamObj(keynode));
        }
        else {
            key = SyntaxTreeDefaultExprCoder(cs, keynode);
        }
        Expr value = SyntaxTreeDefaultExprCoder(cs, valuenode);
        WRITE_EXPR(cs, record, 2 * i, key);
        WRITE_EXPR(cs, record, 2 * i + 1, value);
    }
    return record;
}

static Obj SyntaxTreeFloatLazy(Obj result, Expr expr)
{
    Obj string = GET_VALUE_FROM_CURRENT_BODY(READ_EXPR(expr, 1));
    AssPRec(result, RNamName("value"), string);
    return result;
}

static Obj SyntaxTreeFloatEager(Obj result, Expr expr)
{
    Obj   value = GET_VALUE_FROM_CURRENT_BODY(READ_EXPR(expr, 0));
    Obj   string = GET_VALUE_FROM_CURRENT_BODY(READ_EXPR(expr, 1));
    UChar chr = (UChar)READ_EXPR(expr, 2);
    AssPRec(result, RNamName("value"), value);
    AssPRec(result, RNamName("string"), string);
    AssPRec(result, RNamName("mark"), ObjsChar[chr]);
    return result;
}

static Expr SyntaxTreeCodeFloatLazy(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeFloatLazy", node);
    Obj value = ElmRecST(EXPR_FLOAT_LAZY, node, "value");
    return CodeLazyFloatExpr(cs, value, 0);
}

static Expr SyntaxTreeCodeFloatEager(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeFloatEager", node);
    Obj  value = ElmRecST(EXPR_FLOAT_EAGER, node, "value");
    Obj  string = ElmRecST(EXPR_FLOAT_EAGER, node, "string");
    Obj  mark = ElmRecST(EXPR_FLOAT_EAGER, node, "mark");
    Expr fl = NewStatOrExpr(cs, EXPR_FLOAT_EAGER, 3 * sizeof(UInt), 0);
    WRITE_EXPR(cs, fl, 0, AddValueToBody(cs, value));
    WRITE_EXPR(cs, fl, 1, AddValueToBody(cs, string));
    WRITE_EXPR(cs, fl, 2, (UInt)CHAR_VALUE(mark));
    return fl;
}

static Obj SyntaxTreeIf(Obj result, Stat stat)
{
    Obj cond;
    Obj then;
    Obj pair;
    Obj branches;

    Int i, nr;

    nr = SIZE_STAT(stat) / (2 * sizeof(Stat));
    branches = NEW_PLIST(T_PLIST, nr);

    AssPRec(result, RNamName("branches"), branches);

    for (i = 0; i < nr; i++) {
        cond = SyntaxTreeCompiler(READ_STAT(stat, 2 * i));
        then = SyntaxTreeCompiler(READ_STAT(stat, 2 * i + 1));

        pair = NEW_PREC(2);
        AssPRec(pair, RNamName("condition"), cond);
        AssPRec(pair, RNamName("body"), then);

        PushPlist(branches, pair);
    }
    return result;
}

static Obj SyntaxTreeCompilePragma(Obj result, Stat stat)
{
    Obj message = GET_VALUE_FROM_CURRENT_BODY(READ_EXPR(stat, 0));
    AssPRec(result, RNamName("value"), message);
    return result;
}

static Expr SyntaxTreeCodeIf(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeIf", node);
    UInt1 tnum = GetTypeTNum(node);
    Obj   branches = ElmRecST(tnum, node, "branches");
    UInt  len = LEN_LIST(branches);
    Expr  ifexpr = NewStatOrExpr(cs, tnum, 2 * len * sizeof(Expr), 0);
    for (int i = 0; i < len; i++) {
        Obj  condbodypair = ELM_LIST(branches, i + 1);
        Obj  conditionnode = ElmRecST(tnum, condbodypair, "condition");
        Obj  bodynode = ElmRecST(tnum, condbodypair, "body");
        Expr condition = SyntaxTreeDefaultExprCoder(cs, conditionnode);
        Stat body = SyntaxTreeDefaultStatCoder(cs, bodynode);
        WRITE_EXPR(cs, ifexpr, 2 * i, condition);
        WRITE_EXPR(cs, ifexpr, 2 * i + 1, body);
    }
    return ifexpr;
}

static Expr SyntaxTreeCodeImmediateInteger(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeImmediateInteger", node);
    Obj value = ElmRecST(EXPR_INT, node, "value");
    RequireSmallIntEx("SyntaxTreeCodeImmediateInteger", value,
                      ".value");
    return INTEXPR_INT(INT_INTOBJ(value));
}

static Expr SyntaxTreeCodeValue(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeValue", node);
    UInt1 tnum = GetTypeTNum(node);
    Obj   value = ElmRecST(tnum, node, "value");
    Expr  expr = NewStatOrExpr(cs, tnum, sizeof(UInt), 0);
    Int   ix = AddValueToBody(cs, value);
    WRITE_EXPR(cs, expr, 0, ix);
    return expr;
}

static Expr SyntaxTreeCodeChar(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeChar", node);
    Obj  chr = ElmRecST(EXPR_CHAR, node, "value");
    Char currchar = CHAR_VALUE(chr);
    Expr lit = NewStatOrExpr(cs, EXPR_CHAR, sizeof(UInt), 0);
    WRITE_EXPR(cs, lit, 0, currchar);
    return lit;
}

static Obj SyntaxTreeFunc(Obj result, Obj func)
{
    Obj stats;

    Bag oldFrame;
    Int narg;
    Int nloc;

    if (NAME_FUNC(func)) {
        AssPRec(result, RNamName("name"), NAME_FUNC(func));
    }

    narg = NARG_FUNC(func);
    if (narg < 0) {
        AssPRec(result, RNamName("variadic"), True);
        narg = -narg;
    }
    else {
        AssPRec(result, RNamName("variadic"), False);
    }
    AssPRec(result, RNamName("narg"), INTOBJ_INT(narg));
    nloc = NLOC_FUNC(func);
    AssPRec(result, RNamName("nloc"), INTOBJ_INT(nloc));

    // names of arguments and locals
    AssPRec(result, RNamName("nams"), NAMS_FUNC(func));

    // switch to this function (so that 'READ_STAT' and 'READ_EXPR' work)
    oldFrame = SWITCH_TO_NEW_LVARS(func, narg, nloc);
    stats = SyntaxTreeCompiler(OFFSET_FIRST_STAT);
    SWITCH_TO_OLD_LVARS(oldFrame);

    AssPRec(result, RNamName("stats"), stats);

    return result;
}

static Expr SyntaxTreeCodeFunc(CodeState * cs, Obj node)
{
    RequirePlainRec("SyntaxTreeCodeFunc", node);
    Int narg = INT_INTOBJ(ElmRecST(EXPR_FUNC, node, "narg"));
    Int nloc = INT_INTOBJ(ElmRecST(EXPR_FUNC, node, "nloc"));
    Obj nams = ElmRecST(EXPR_FUNC, node, "nams");
    Obj variadic = ElmRecST(EXPR_FUNC, node, "variadic");
    if (variadic == True) {
        narg = -narg;
    }
    CodeFuncExprBegin(cs, narg, nloc, nams, 0, 0);
    Obj  stat_rec = ElmRecST(EXPR_FUNC, node, "stats");
    Obj  body_stats = ElmRecST(EXPR_FUNC, stat_rec, "statements");
    UInt nr_stats = LEN_LIST(body_stats);
    for (int i = 1; i <= nr_stats; i++) {
        Expr current =
            SyntaxTreeDefaultStatCoder(cs, ELM_LIST(body_stats, i));
        PushStat(current);
    }
    return CodeFuncExprEnd(cs, nr_stats, FALSE, 0);
}

static Obj FuncSYNTAX_TREE_CODE(Obj self, Obj tree)
{
    RequirePlainRec(SELF_NAME, tree);
    CodeState cs;
    CodeBegin(&cs);
    SyntaxTreeCodeFunc(&cs, tree);
    Obj func = CodeEnd(&cs, 0);
    if (IsbPRec(tree, RNamName("name"))) {
        Obj name = ELM_REC(tree, RNamName("name"));
        SET_NAME_FUNC(func, name);
    }
    return func;
}

static const CompilerT Compilers[] = {
    COMPILER_(STAT_PROCCALL_0ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(STAT_PROCCALL_1ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(STAT_PROCCALL_2ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(STAT_PROCCALL_3ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(STAT_PROCCALL_4ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(STAT_PROCCALL_5ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(STAT_PROCCALL_6ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(STAT_PROCCALL_XARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),

    COMPILER_(STAT_PROCCALL_OPTS, ARG_EXPR_("opts"), ARG_STAT_("call")),

    COMPILER_(STAT_EMPTY),

    COMPILER_(STAT_SEQ_STAT, ARGS_STAT("statements")),
    COMPILER_(STAT_SEQ_STAT2, ARGS_STAT("statements")),
    COMPILER_(STAT_SEQ_STAT3, ARGS_STAT("statements")),
    COMPILER_(STAT_SEQ_STAT4, ARGS_STAT("statements")),
    COMPILER_(STAT_SEQ_STAT5, ARGS_STAT("statements")),
    COMPILER_(STAT_SEQ_STAT6, ARGS_STAT("statements")),
    COMPILER_(STAT_SEQ_STAT7, ARGS_STAT("statements")),

    COMPILER(STAT_IF, SyntaxTreeIf, SyntaxTreeCodeIf),
    COMPILER(STAT_IF_ELSE, SyntaxTreeIf, SyntaxTreeCodeIf),
    COMPILER(STAT_IF_ELIF, SyntaxTreeIf, SyntaxTreeCodeIf),
    COMPILER(STAT_IF_ELIF_ELSE, SyntaxTreeIf, SyntaxTreeCodeIf),

    COMPILER_(STAT_FOR,
              ARG_EXPR_("variable"),
              ARG_EXPR_("collection"),
              ARGS_STAT("body")),
    COMPILER_(STAT_FOR2,
              ARG_EXPR_("variable"),
              ARG_EXPR_("collection"),
              ARGS_STAT("body")),
    COMPILER_(STAT_FOR3,
              ARG_EXPR_("variable"),
              ARG_EXPR_("collection"),
              ARGS_STAT("body")),

    COMPILER_(STAT_FOR_RANGE,
              ARG_EXPR_("variable"),
              ARG_EXPR_("collection"),
              ARGS_STAT("body")),
    COMPILER_(STAT_FOR_RANGE2,
              ARG_EXPR_("variable"),
              ARG_EXPR_("collection"),
              ARGS_STAT("body")),
    COMPILER_(STAT_FOR_RANGE3,
              ARG_EXPR_("variable"),
              ARG_EXPR_("collection"),
              ARGS_STAT("body")),

    COMPILER_(STAT_WHILE, ARG_EXPR_("condition"), ARGS_STAT("body")),
    COMPILER_(STAT_WHILE2, ARG_EXPR_("condition"), ARGS_STAT("body")),
    COMPILER_(STAT_WHILE3, ARG_EXPR_("condition"), ARGS_STAT("body")),

    COMPILER_(STAT_REPEAT, ARG_EXPR_("condition"), ARGS_STAT("body")),
    COMPILER_(STAT_REPEAT2, ARG_EXPR_("condition"), ARGS_STAT("body")),
    COMPILER_(STAT_REPEAT3, ARG_EXPR_("condition"), ARGS_STAT("body")),

#ifdef HPCGAP
    COMPILER_(STAT_ATOMIC,
              ARG_STAT_("body"),
              ARGS_EXPR("locks")),    // TODO: better output
#endif

    COMPILER_(STAT_BREAK),
    COMPILER_(STAT_CONTINUE),
    COMPILER_(STAT_RETURN_OBJ, ARG_EXPR_("obj")),
    COMPILER_(STAT_RETURN_VOID),

    COMPILER_(STAT_ASS_LVAR,
              ARG_EXPR("lvar", ObjInt_UInt, SyntaxTreeCodeObjInt),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_UNB_LVAR,
              ARG_EXPR("lvar", ObjInt_UInt, SyntaxTreeCodeObjInt)),

    COMPILER_(STAT_ASS_HVAR,
              ARG_EXPR("hvar", ObjInt_UInt, SyntaxTreeCodeObjInt),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_UNB_HVAR,
              ARG_EXPR("hvar", ObjInt_UInt, SyntaxTreeCodeObjInt)),

    COMPILER_(STAT_ASS_GVAR,
              ARG_EXPR("gvar", NameGVar, SyntaxTreeCodeGVar),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_UNB_GVAR, ARG_EXPR("gvar", NameGVar, SyntaxTreeCodeGVar)),

    COMPILER_(
        STAT_ASS_LIST, ARG_EXPR_("list"), ARG_EXPR_("pos"), ARG_EXPR_("rhs")),
    COMPILER_(STAT_ASS_MAT,
              ARG_EXPR_("list"),
              ARG_EXPR_("row"),
              ARG_EXPR_("col"),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_ASSS_LIST,
              ARG_EXPR_("list"),
              ARG_EXPR_("poss"),
              ARG_EXPR_("rhss")),
    COMPILER_(STAT_ASS_LIST_LEV,
              ARG_EXPR_("lists"),
              ARG_EXPR_("pos"),
              ARG_EXPR_("rhss"),
              ARG_EXPR("level", ObjInt_UInt, SyntaxTreeCodeObjInt)),
    COMPILER_(STAT_ASSS_LIST_LEV,
              ARG_EXPR_("lists"),
              ARG_EXPR_("poss"),
              ARG_EXPR_("rhss"),
              ARG_EXPR("level", ObjInt_UInt, SyntaxTreeCodeObjInt)),
    COMPILER_(STAT_UNB_LIST, ARG_EXPR_("list"), ARG_EXPR_("pos")),

    COMPILER_(STAT_ASS_REC_NAME,
              ARG_EXPR_("record"),
              ARG_EXPR("rnam", SyntaxTreeRNam, SyntaxTreeCodeRNamObj),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_ASS_REC_EXPR,
              ARG_EXPR_("record"),
              ARG_EXPR_("expression"),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_UNB_REC_NAME,
              ARG_EXPR_("record"),
              ARG_EXPR("rnam", SyntaxTreeRNam, SyntaxTreeCodeRNamObj)),
    COMPILER_(
        STAT_UNB_REC_EXPR, ARG_EXPR_("record"), ARG_EXPR_("expression")),

    COMPILER_(STAT_ASS_POSOBJ,
              ARG_EXPR_("posobj"),
              ARG_EXPR_("pos"),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_UNB_POSOBJ, ARG_EXPR_("posobj"), ARG_EXPR_("pos")),

    COMPILER_(STAT_ASS_COMOBJ_NAME,
              ARG_EXPR_("comobj"),
              ARG_EXPR("rnam", SyntaxTreeRNam, SyntaxTreeCodeRNamObj),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_ASS_COMOBJ_EXPR,
              ARG_EXPR_("comobj"),
              ARG_EXPR_("expression"),
              ARG_EXPR_("rhs")),
    COMPILER_(STAT_UNB_COMOBJ_NAME,
              ARG_EXPR_("comobj"),
              ARG_EXPR("rnam", SyntaxTreeRNam, SyntaxTreeCodeRNamObj)),
    COMPILER_(
        STAT_UNB_COMOBJ_EXPR, ARG_EXPR_("comobj"), ARG_EXPR_("expression")),

    COMPILER_(
        STAT_INFO, ARG_EXPR_("sel"), ARG_EXPR_("lev"), ARGS_EXPR("args")),
    COMPILER_(STAT_ASSERT_2ARGS, ARG_EXPR_("level"), ARG_EXPR_("condition")),
    COMPILER_(STAT_ASSERT_3ARGS,
              ARG_EXPR_("level"),
              ARG_EXPR_("condition"),
              ARG_EXPR_("message")),
    COMPILER(STAT_PRAGMA, SyntaxTreeCompilePragma, SyntaxTreeCodeValue),


    // Statements
    COMPILER_(EXPR_FUNCCALL_0ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(EXPR_FUNCCALL_1ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(EXPR_FUNCCALL_2ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(EXPR_FUNCCALL_3ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(EXPR_FUNCCALL_4ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(EXPR_FUNCCALL_5ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(EXPR_FUNCCALL_6ARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),
    COMPILER_(EXPR_FUNCCALL_XARGS, ARG_EXPR_("funcref"), ARGS_EXPR("args")),

    COMPILER(EXPR_FUNC, SyntaxTreeFuncExpr, SyntaxTreeCodeFunc),

    COMPILER_(EXPR_FUNCCALL_OPTS, ARG_EXPR_("opts"), ARG_EXPR_("call")),


    COMPILER_(EXPR_OR, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_AND, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_NOT, ARG_EXPR_("op")),
    COMPILER_(EXPR_EQ, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_NE, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_LT, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_GE, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_GT, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_LE, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_IN, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_SUM, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_AINV, ARG_EXPR_("op")),
    COMPILER_(EXPR_DIFF, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_PROD, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_QUO, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_MOD, ARG_EXPR_("left"), ARG_EXPR_("right")),
    COMPILER_(EXPR_POW, ARG_EXPR_("left"), ARG_EXPR_("right")),

    COMPILER(
        EXPR_INT, SyntaxTreeEvalCompiler, SyntaxTreeCodeImmediateInteger),
    COMPILER(EXPR_INTPOS, SyntaxTreeEvalCompiler, SyntaxTreeCodeValue),
    COMPILER_(EXPR_TRUE),
    COMPILER_(EXPR_FALSE),
    COMPILER_(EXPR_TILDE),
    COMPILER(EXPR_CHAR, SyntaxTreeEvalCompiler, SyntaxTreeCodeChar),
    COMPILER_(EXPR_PERM, ARGS_EXPR("cycles")),
    COMPILER_(EXPR_PERM_CYCLE, ARGS_EXPR("points")),
    COMPILER_(EXPR_LIST, ARGS_EXPR("list")),
    COMPILER_(EXPR_LIST_TILDE, ARGS_EXPR("list")),
    COMPILER(EXPR_RANGE, SyntaxTreeRangeExpr, SyntaxTreeCodeRangeExpr),
    COMPILER(EXPR_STRING, SyntaxTreeEvalCompiler, SyntaxTreeCodeValue),
    COMPILER(EXPR_REC, SyntaxTreeRecExpr, SyntaxTreeCodeRecExpr),
    COMPILER(EXPR_REC_TILDE, SyntaxTreeRecExpr, SyntaxTreeCodeRecExpr),

    COMPILER(
        EXPR_FLOAT_EAGER, SyntaxTreeFloatEager, SyntaxTreeCodeFloatEager),
    COMPILER(EXPR_FLOAT_LAZY, SyntaxTreeFloatLazy, SyntaxTreeCodeFloatLazy),

    // EXPR_REF_LVAR is encoded differently from all other
    //           references to LVARs, so we have to treat
    //           them specially here
    COMPILER(EXPR_REF_LVAR, SyntaxTreeRefLVar, SyntaxTreeCodeRefLVar),
    COMPILER_(EXPR_ISB_LVAR,
              ARG_EXPR("lvar", ObjInt_UInt, SyntaxTreeCodeObjInt)),

    COMPILER_(EXPR_REF_HVAR,
              ARG_EXPR("hvar", ObjInt_UInt, SyntaxTreeCodeObjInt)),
    COMPILER_(EXPR_ISB_HVAR,
              ARG_EXPR("hvar", ObjInt_UInt, SyntaxTreeCodeObjInt)),

    COMPILER_(EXPR_REF_GVAR, ARG_EXPR("gvar", NameGVar, SyntaxTreeCodeGVar)),
    COMPILER_(EXPR_ISB_GVAR, ARG_EXPR("gvar", NameGVar, SyntaxTreeCodeGVar)),

    // TODO: can this be unified?
    COMPILER_(EXPR_ELM_LIST, ARG_EXPR_("list"), ARG_EXPR_("pos")),
    COMPILER_(
        EXPR_ELM_MAT, ARG_EXPR_("list"), ARG_EXPR_("row"), ARG_EXPR_("col")),
    COMPILER_(EXPR_ELMS_LIST, ARG_EXPR_("list"), ARG_EXPR_("poss")),
    COMPILER_(EXPR_ELM_LIST_LEV,
              ARG_EXPR_("lists"),
              ARGS_EXPR("pos"),
              ARG_EXPR("level", ObjInt_UInt, SyntaxTreeCodeObjInt)),
    COMPILER_(EXPR_ELMS_LIST_LEV,
              ARG_EXPR_("lists"),
              ARG_EXPR_("poss"),
              ARG_EXPR("level", ObjInt_UInt, SyntaxTreeCodeObjInt)),
    COMPILER_(EXPR_ISB_LIST, ARG_EXPR_("list"), ARGS_EXPR("pos")),
    COMPILER_(EXPR_ELM_REC_NAME,
              ARG_EXPR_("record"),
              ARG_EXPR("name", SyntaxTreeRNam, SyntaxTreeCodeRNamObj)),
    COMPILER_(
        EXPR_ELM_REC_EXPR, ARG_EXPR_("record"), ARG_EXPR_("expression")),
    COMPILER_(EXPR_ISB_REC_NAME,
              ARG_EXPR_("record"),
              ARG_EXPR("name", SyntaxTreeRNam, SyntaxTreeCodeRNamObj)),
    COMPILER_(
        EXPR_ISB_REC_EXPR, ARG_EXPR_("record"), ARG_EXPR_("expression")),
    COMPILER_(EXPR_ELM_POSOBJ, ARG_EXPR_("posobj"), ARG_EXPR_("pos")),
    COMPILER_(EXPR_ISB_POSOBJ, ARG_EXPR_("posobj"), ARG_EXPR_("pos")),
    COMPILER_(EXPR_ELM_COMOBJ_NAME,
              ARG_EXPR_("comobj"),
              ARG_EXPR("name", SyntaxTreeRNam, SyntaxTreeCodeRNamObj)),
    COMPILER_(
        EXPR_ELM_COMOBJ_EXPR, ARG_EXPR_("comobj"), ARG_EXPR_("expression")),
    COMPILER_(EXPR_ISB_COMOBJ_NAME,
              ARG_EXPR_("comobj"),
              ARG_EXPR("name", SyntaxTreeRNam, SyntaxTreeCodeRNamObj)),
    COMPILER_(
        EXPR_ISB_COMOBJ_EXPR, ARG_EXPR_("comobj"), ARG_EXPR_("expression")),
};

static Obj FuncSYNTAX_TREE(Obj self, Obj func)
{
    Obj result;

    if (!IS_FUNC(func) || IsKernelFunction(func) || IS_OPERATION(func)) {
        RequireArgument(SELF_NAME, func, "must be a plain GAP function");
    }

    result = NewSyntaxTreeNode(EXPR_FUNC);
    return SyntaxTreeFunc(result, func);
}

static StructGVarFunc GVarFuncs[] = { GVAR_FUNC_1ARGS(SYNTAX_TREE, func),
                                      GVAR_FUNC_1ARGS(SYNTAX_TREE_CODE, tree),
                                      { 0, 0, 0, 0, 0 } };

static Int InitKernel(StructInitInfo * module)
{
    // init filters and functions
    InitHdlrFuncsFromTable(GVarFuncs);

    InitGlobalBag(&typeStrings, "typeStrings");
    InitGlobalBag(&typeRec, "typeRec");

    return 0;
}

static Int InitLibrary(StructInitInfo * module)
{
    // init filters and functions
    InitGVarFuncsFromTable(GVarFuncs);

    typeStrings = NEW_PLIST(T_PLIST, ARRAY_SIZE(Compilers));
    typeRec = NEW_PREC(0);
    for (UInt tnum = 0; tnum < ARRAY_SIZE(Compilers); tnum++) {
        const char * str = Compilers[tnum].name;
        if (str) {
            AssPRec(typeRec, RNamName(str), ObjInt_UInt(tnum));
            ASS_LIST(typeStrings, tnum + 1, MakeImmString(str));
        }
    }


    return 0;
}

static StructInitInfo module = {
    // init struct using C99 designated initializers; for a full list of
    // fields, please refer to the definition of StructInitInfo
    .type = MODULE_BUILTIN,
    .name = "syntaxtree",
    .initKernel = InitKernel,
    .initLibrary = InitLibrary,
};

StructInitInfo * InitInfoSyntaxTree(void)
{
    return &module;
}

93%


¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.