Esempio n. 1
0
def compFuncApp(target, linkage, funcType):
    "funcType as string: 'compiled' or 'compound'"
    valTarg = target == VAL
    retLink = linkage == RET

    funcList = (["val = COMPLABOBJ(func);", "goto COMP_LABEL;"] if funcType
                == 'compiled' else ["save(cont);", "goto APPLY_COMPOUND;"])

    # typical function call, eg (f 5)
    if valTarg and not retLink:
        return InstrSeq([FUNC], ALLREGS,
                        [f"cont = LABELOBJ(_{linkage});"] + funcList)

    # target is func, eg in ((f 4) 5)
    if not valTarg and not retLink:
        (funcReturn, ), (funcReturnInfo, ) = branchesAndInfos(
            ('FUNC_RETURN', ))

        return InstrSeq([FUNC], ALLREGS,
                        ([f"cont = LABELOBJ(_{funcReturn});"] + funcList + [
                            funcReturnInfo,
                            f"{target} = val;",
                            f"goto {linkage};",
                        ]))

    # this gets called, but I don't understand when
    if valTarg and retLink:
        return InstrSeq([FUNC, CONT], ALLREGS, funcList)

    Exception('bad function call', 'compFuncApp')
Esempio n. 2
0
def compileLinkage(linkage):
    if linkage == RET:
        return InstrSeq([CONT], [], ['goto CONTINUE;'])

    if linkage == NEX:
        return InstrSeq([], [], [])

    return InstrSeq([], [], [f'goto {linkage};'])
Esempio n. 3
0
def constructArglist(argCodes):
    if not argCodes:
        return InstrSeq([], [ARGLIST], ["arglist = NULLOBJ;"])

    lastArg, *restArgs = reversed(argCodes)

    codeToGetLastArg = appendInstrSeqs(
        lastArg, InstrSeq([VAL], [ARGLIST], ["arglist = CONS(val, NULLOBJ);"]))

    return (codeToGetLastArg if not restArgs else preserving(
        [ENV], codeToGetLastArg, codeToGetRestArgs(restArgs)))
Esempio n. 4
0
def compLambda(expr, target=VAL, linkage=NEX):
    (funcEntry, afterLambda), (funcEntryInfo, afterLambdaInfo) = \
        branchesAndInfos(('ENTRY', 'AFTER_LAMBDA'))

    return appendInstrSeqs(
        tackOnInstrSeq(
            endWithLink(
                afterLambda if linkage == NEX else linkage,
                InstrSeq([ENV], [target],
                         [f"{target} = COMPOBJ(_{funcEntry}, env);"])),
            compLambdaBody(expr, funcEntryInfo)),
        InstrSeq([], [], [afterLambdaInfo]))
Esempio n. 5
0
def codeToGetRestArgs(argCodes):
    nextArg, *restArgs = argCodes

    codeForNextArg = preserving([ARGLIST], nextArg,
                                InstrSeq([VAL, ARGLIST], [ARGLIST],
                                         ["arglist = CONS(val, arglist);"]))

    return (codeForNextArg if not restArgs else preserving(
        [ENV], codeForNextArg, codeToGetRestArgs(restArgs)))
Esempio n. 6
0
    def comp(expr, target, linkage):
        _, variable, value = transformSugarDef(expr)

        return endWithLink(
            linkage,
            preserving(
                [ENV], compExp(value, VAL, NEX),
                InstrSeq([ENV, VAL], [target],
                         [f'{CFunc}(NAMEOBJ("{variable}"), val, env);'])))
Esempio n. 7
0
def compLambdaBody(expr, funcEntryInfo):
    _, params, *body = expr

    return appendInstrSeqs(
        InstrSeq([ENV, FUNC, ARGLIST], [ENV], [
            funcEntryInfo,
            "env = COMPENVOBJ(func);",
            f'unev = parse("{schemify(params)}\\n");',
            "env = extendEnv(unev, arglist, env);",
        ]), compSeq(body, VAL, RET))
Esempio n. 8
0
def compApp(expr, target=VAL, linkage=NEX):
    function, *arguments = expr

    return preserving(
        [ENV, CONT], compExp(function, target=FUNC),
        preserving(
            [FUNC, CONT],
            constructArglist([compExp(arg) for arg in arguments]),
            compFuncCall(target, linkage)
            if function not in PRIMITIVES else endWithLink(
                linkage,
                InstrSeq([FUNC, ARGLIST], [target],
                         [f"{target} = applyPrimitive(func, arglist);"]))))
Esempio n. 9
0
def compIf(expr, target=VAL, linkage=NEX):
    (trueBranch, _, afterIf), (trueBranchInfo, falseBranchInfo, afterIfInfo) = \
    branchesAndInfos(
        ['TRUE_BRANCH', 'FALSE_BRANCH', 'AFTER_IF'])

    (_, ifTest, ifThen, ifElse) = expr

    testCode = compExp(ifTest, VAL, NEX)
    thenCode = compExp(ifThen, target, linkage)
    elseCode = compExp(ifElse, target, afterIf if linkage == NEX else linkage)

    return preserving([ENV, CONT], testCode,
                      appendInstrSeqs(
                          InstrSeq([VAL], [],
                                   [f"if (isTrue(val)) goto {trueBranch};"]),
                          parallelInstrSeqs(
                              appendInstrSeqs(falseBranchInfo, elseCode),
                              appendInstrSeqs(trueBranchInfo, thenCode)),
                          afterIfInfo))
Esempio n. 10
0
def compFuncCall(target, linkage):
    branches, infos = branchesAndInfos((
        'PRIMITIVE',
        'COMPOUND',
        'COMPILED',
        'AFTER_CALL',
    ))

    (primitiveBranch, compoundBranch, _, afterCall) = branches

    (primitiveBranchInfo, compoundBranchInfo, compiledBranchInfo,
     afterCallInfo) = infos

    endLabel = afterCall if linkage == NEX else linkage

    applyPrimitiveSeq = InstrSeq(
        [FUNC, ARGLIST], [target],
        [f"{target} = applyPrimitive(func, arglist);"])

    def makeTestGotoSeq(testString, label):
        return InstrSeq([FUNC], [], [f"if ({testString}(func)) goto {label};"])

    # calling compFuncApp twice generates two different endLabels

    return appendInstrSeqs(
        makeTestGotoSeq('isPrimitive', primitiveBranch),
        makeTestGotoSeq('isCompound', compoundBranch),
        parallelInstrSeqs(
            appendInstrSeqs(compiledBranchInfo,
                            compFuncApp(target, endLabel, 'compiled')),
            parallelInstrSeqs(
                appendInstrSeqs(compoundBranchInfo,
                                compFuncApp(target, endLabel, 'compound')),
                appendInstrSeqs(primitiveBranchInfo,
                                endWithLink(linkage, applyPrimitiveSeq)))),
        afterCallInfo)
Esempio n. 11
0
def compQuote(expr, target, linkage):
    _, text = expr

    return endWithLink(
        linkage,
        InstrSeq([], [target], [f'{target} = parse("{schemify(text)}\\n");']))
Esempio n. 12
0
def compVar(expr, target, linkage):
    return endWithLink(
        linkage,
        InstrSeq([ENV], [target],
                 [f'{target} = lookup(NAMEOBJ("{expr}"), env);']))
Esempio n. 13
0
def compNum(expr, target, linkage):
    return endWithLink(linkage,
                       InstrSeq([], [target], [f"{target} = NUMOBJ({expr});"]))
Esempio n. 14
0
 def makeTestGotoSeq(testString, label):
     return InstrSeq([FUNC], [], [f"if ({testString}(func)) goto {label};"])