//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 15 Sep 05 Brian Frank Creation
//
**
** Assembler assembles all the TypeDefs into their fcode representation.
**
class Assembler : CompilerSupport, FConst
{
//////////////////////////////////////////////////////////////////////////
// Construction
//////////////////////////////////////////////////////////////////////////
new make(Compiler compiler)
: super(compiler)
{
}
//////////////////////////////////////////////////////////////////////////
// Assemble
//////////////////////////////////////////////////////////////////////////
FPod assemblePod()
{
fpod = FPod(ns, pod.name, null)
fpod.name = compiler.input.podName
fpod.version = compiler.input.version
fpod.depends = compiler.depends
fpod.meta = assembleMeta
fpod.index = pod.index
fpod.ftypes = FType[,]
types.each |TypeDef t|
{
fpod.ftypes.add(assembleType(t))
}
return fpod
}
private Str:Str assembleMeta()
{
meta := pod.meta
meta["pod.fcode"] = (!types.isEmpty).toStr
meta["pod.js"] = (compiler.cjs != null || compiler.isSys).toStr
return meta
}
private FType assembleType(TypeDef def)
{
t := FType(fpod)
t.hollow = false
t.flags = def.flags
t.self = typeRef(def)
t.fbase = (def.base == null) ? -1 : typeRef(def.base)
t.fmixins = def.mixins.map |CType m->Int| { typeRef(m) }
t.ffields = def.fieldDefs.map |FieldDef f->FField| { assembleField(t, f) }
t.fmethods = def.methodDefs.map |MethodDef m->FMethod| { assembleMethod(t, m) }
attrs := AttrAsm(compiler, fpod)
if (compiler.input.mode == CompilerInputMode.str)
attrs.sourceFile(def.loc.fileUri)
else
attrs.sourceFile(def.loc.filename)
attrs.lineNumber(def.loc.line)
attrs.facets(def.facets)
t.fattrs = attrs.attrs
return t
}
FField assembleField(FType fparent, FieldDef def)
{
f := FField(fparent)
f.nameIndex = name(def.name)
f.flags = def.flags
f.typeRef = typeRef(def.fieldType)
attrs := AttrAsm(compiler, fpod)
attrs.lineNumber(def.loc.line)
attrs.facets(def.facets)
if (def.enumDef != null) attrs.enumOrdinal(def.enumDef.ordinal)
f.fattrs = attrs.attrs
return f;
}
FMethod assembleMethod(FType fparent, MethodDef def)
{
attrs := AttrAsm(compiler, fpod)
m := FMethod(fparent)
m.nameIndex = name(def.name)
m.flags = def.flags
m.ret = typeRef(def.ret)
m.inheritedRet = typeRef(def.inheritedReturnType)
m.paramCount = def.params.size
m.localCount = def.vars.size - def.params.size
m.vars = def.vars.map |MethodVar v->FMethodVar|
{
f := FMethodVar(m)
f.nameIndex = name(v.name)
f.typeRef = typeRef(v.paramDef?.paramType ?: v.ctype)
f.flags = v.flags
if (v.paramDef != null)
{
f.defNameIndex = name(ParamDefaultAttr)
f.def = assembleExpr(v.paramDef.def)
}
return f
}
m.code = assembleCode(def, attrs)
attrs.lineNumber(def.loc.line)
attrs.facets(def.facets)
m.fattrs = attrs.attrs
return m;
}
//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////
Int typeRef(CType type)
{
return fpod.addTypeRef(type)
}
Int name(Str val)
{
return fpod.addName(val)
}
private Buf? assembleCode(MethodDef def , AttrAsm attrs)
{
block := def.code
if (block == null) return null
asm := CodeAsm(compiler, def.loc, fpod, def)
if (def.ctorChain != null) asm.expr(def.ctorChain)
asm.block(block)
if (asm.errCount > 0) attrs.add(ErrTableAttr, asm.finishErrTable)
if (asm.lineCount > 0) attrs.add(LineNumbersAttr, asm.finishLines)
return asm.finishCode
}
private Buf? assembleExpr(Expr? expr)
{
if (expr == null) return null
asm := CodeAsm(compiler, expr.loc, fpod, null)
asm.expr(expr)
return asm.finishCode
}
//////////////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////////////
FPod? fpod
}