//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 15 Sep 05 Brian Frank Creation
// 29 Aug 06 Brian Frank Ported from Java to Fan
//
**
** CNamespace is responsible for providing a unified view pods, types,
** and slots between the entities currently being compiled and the
** entities being imported from pre-compiled pods.
**
abstract class CNamespace
{
//////////////////////////////////////////////////////////////////////////
// Initialization
//////////////////////////////////////////////////////////////////////////
**
** Once the sub class is initialized, it must call this
** method to initialize our all predefined values.
**
protected Void init()
{
// sys pod
sysPod = resolvePod("sys", null)
// error placeholder type
error = GenericParameterType(this, "Error")
// nothing placeholder type
nothingType = GenericParameterType(this, "Nothing")
// generic parameter types
genericParams =
[
"A": genericParam("A"),
"B": genericParam("B"),
"C": genericParam("C"),
"D": genericParam("D"),
"E": genericParam("E"),
"F": genericParam("F"),
"G": genericParam("G"),
"H": genericParam("H"),
"K": genericParam("K"),
"L": genericParam("L"),
"M": genericParam("M"),
"R": genericParam("R"),
"V": genericParam("V"),
].ro()
// types
objType = sysType("Obj")
boolType = sysType("Bool")
enumType = sysType("Enum")
facetType = sysType("Facet")
intType = sysType("Int")
floatType = sysType("Float")
decimalType = sysType("Decimal")
strType = sysType("Str")
strBufType = sysType("StrBuf")
durationType = sysType("Duration")
listType = sysType("List")
mapType = sysType("Map")
funcType = sysType("Func")
errType = sysType("Err")
podType = sysType("Pod")
typeType = sysType("Type")
slotType = sysType("Slot")
fieldType = sysType("Field")
methodType = sysType("Method")
rangeType = sysType("Range")
testType = sysType("Test")
uriType = sysType("Uri")
voidType = sysType("Void")
fieldNotSetErrType = sysType("FieldNotSetErr")
notImmutableErrType = sysType("NotImmutableErr")
// methods
objTrap = sysMethod(objType, "trap")
objWith = sysMethod(objType, "with")
objToImmutable = sysMethod(objType, "toImmutable")
boolNot = sysMethod(boolType, "not")
intIncrement = sysMethod(intType, "increment")
intDecrement = sysMethod(intType, "decrement")
intPlus = sysMethod(intType, "plus")
floatPlus = sysMethod(floatType, "plus")
floatMinus = sysMethod(floatType, "minus")
strPlus = sysMethod(strType, "plus")
strBufMake = sysMethod(strBufType, "make")
strBufAdd = sysMethod(strBufType, "add")
strBufToStr = sysMethod(strBufType, "toStr")
listMake = sysMethod(listType, "make")
listMakeObj = sysMethod(listType, "makeObj")
listAdd = sysMethod(listType, "add")
mapMake = sysMethod(mapType, "make")
mapSet = sysMethod(mapType, "set")
enumOrdinal = sysMethod(enumType, "ordinal")
funcBind = sysMethod(funcType, "bind")
rangeMakeInclusive = sysMethod(rangeType, "makeInclusive")
rangeMakeExclusive = sysMethod(rangeType, "makeExclusive")
slotFindMethod = sysMethod(slotType, "findMethod")
slotFindFunc = sysMethod(slotType, "findFunc")
podFind = sysMethod(podType, "find")
podLocale = sysMethod(podType, "locale")
typePod = sysMethod(typeType, "pod")
typeField = sysMethod(typeType, "field")
typeMethod = sysMethod(typeType, "method")
funcCall = sysMethod(funcType, "call")
fieldNotSetErrMake = sysMethod(fieldNotSetErrType, "make")
notImmutableErrMake = sysMethod(notImmutableErrType, "make")
// mock methods
mockFlags := FConst.Public + FConst.Virtual
funcEnterCtor = MockMethod(funcType, "enterCtor", mockFlags, voidType, [objType])
funcExitCtor = MockMethod(funcType, "exitCtor", mockFlags, voidType, CType[,])
funcCheckInCtor = MockMethod(funcType, "checkInCtor", mockFlags, voidType, [objType])
itBlockType = FuncType.makeItBlock(objType.toNullable)
itBlockType.inferredSignature = true
}
private CType genericParam(Str name)
{
t := GenericParameterType(this, name)
n := t.toNullable
typeCache[t.signature] = t
typeCache[n.signature] = n
return t
}
private CType sysType(Str name)
{
return sysPod.resolveType(name, true)
}
private CMethod sysMethod(CType t, Str name)
{
m := t.method(name)
if (m == null) throw Err("Cannot resolve '${t.qname}.$name' method in namespace")
return m
}
//////////////////////////////////////////////////////////////////////////
// Cleanup
//////////////////////////////////////////////////////////////////////////
Void cleanup()
{
bridgeCache.each |bridge|
{
try
bridge.cleanup
catch (Err e)
e.trace
}
}
//////////////////////////////////////////////////////////////////////////
// Resolution
//////////////////////////////////////////////////////////////////////////
**
** Resolve to foreign function interface bridge.
** Bridges are loaded once for each compiler session.
**
private CBridge resolveBridge(Str name, Loc? loc)
{
// check cache
bridge := bridgeCache[name]
if (bridge != null) return bridge
// delegate to findBridge
bridge = findBridge(compiler, name, loc)
// put into cache
bridgeCache[name] = bridge
return bridge
}
private Str:CBridge bridgeCache := Str:CBridge[:] // keyed by pod name
**
** Subclass hook to resolve a FFI name to a CBridge implementation.
** Throw CompilerErr if there is a problem resolving the bridge.
** The default implementation attempts to resolve the indexed
** property "compiler.bridge.$name" to a Type qname.
**
protected virtual CBridge findBridge(Compiler compiler, Str name, Loc? loc)
{
// resolve the compiler bridge using indexed props
t := Env.cur.index("compiler.bridge.${name}")
if (t.size > 1)
throw CompilerErr("Multiple FFI bridges available for '$name': $t", loc)
if (t.size == 0)
throw CompilerErr("No FFI bridge available for '$name'", loc)
// construct bridge instance
try
return Type.find(t.first).make([compiler])
catch (Err e)
throw CompilerErr("Cannot construct FFI bridge '$t.first'", loc, e)
}
**
** Attempt to import the specified pod name against our
** dependency library. If not found then throw CompilerErr.
**
CPod resolvePod(Str podName, Loc? loc)
{
// check cache
pod := podCache[podName]
if (pod != null) return pod
if (podName[0] == '[')
{
// we have a FFI, route to bridge
sep := podName.index("]")
ffi := podName[1..<sep]
package := podName[sep+1..-1]
pod = resolveBridge(ffi, loc).resolvePod(package, loc)
}
else
{
// let namespace resolve it
pod = findPod(podName)
if (pod == null)
throw CompilerErr("Pod not found '$podName'", loc)
}
// stash in the cache and return
podCache[podName] = pod
return pod
}
private Str:CPod podCache := Str:CPod[:] // keyed by pod name
**
** Subclass hook to resolve a pod name to a CPod implementation.
** Return null if not found.
**
protected abstract CPod? findPod(Str podName)
**
** Attempt resolve a signature against our dependency
** library. If not a valid signature or it can't be
** resolved, then throw Err.
**
CType resolveType(Str sig)
{
// check our cache first
t := typeCache[sig]
if (t != null) return t
// parse it into a CType
t = TypeParser.resolve(this, sig)
typeCache[sig] = t
return t
}
internal Str:CType typeCache := Str:CType[:] // keyed by signature
**
** Attempt resolve a slot against our dependency
** library. If can't be resolved, then throw Err.
**
CSlot resolveSlot(Str qname)
{
dot := qname.indexr(".")
slot := resolveType(qname[0..<dot]).slot(qname[dot+1..-1])
if (slot == null) throw Err("Cannot resolve slot: $qname")
return slot
}
**
** Map one of the generic parameter types such as "sys::V" into a CType
**
CType genericParameter(Str id)
{
t := genericParams[id]
if (t == null) throw UnknownTypeErr("sys::$id")
return t
}
//////////////////////////////////////////////////////////////////////////
// Compiler
//////////////////////////////////////////////////////////////////////////
** Used for resolveBridge only
internal Compiler compiler() { c ?: throw Err("Compiler not associated with CNamespace") }
internal Compiler? c
//////////////////////////////////////////////////////////////////////////
// Dependencies
//////////////////////////////////////////////////////////////////////////
**
** Map of dependencies keyed by pod name set in ResolveDepends.
**
[Str:CDepend]? depends
//////////////////////////////////////////////////////////////////////////
// Predefined
//////////////////////////////////////////////////////////////////////////
CPod? sysPod { private set }
// generic parameters like sys::K, sys::V
[Str:CType]? genericParams { private set }
// place holder type used for resolve errors
CType? error { private set }
// place holder type used to indicate nothing (like throw expr)
CType? nothingType { private set }
// generic type for it block until we can infer type
FuncType? itBlockType { private set }
CType? objType { private set }
CType? boolType { private set }
CType? enumType { private set }
CType? facetType { private set }
CType? intType { private set }
CType? floatType { private set }
CType? decimalType { private set }
CType? strType { private set }
CType? strBufType { private set }
CType? durationType { private set }
CType? listType { private set }
CType? mapType { private set }
CType? funcType { private set }
CType? errType { private set }
CType? podType { private set }
CType? typeType { private set }
CType? slotType { private set }
CType? fieldType { private set }
CType? methodType { private set }
CType? rangeType { private set }
CType? testType { private set }
CType? uriType { private set }
CType? voidType { private set }
CType? fieldNotSetErrType { private set }
CType? notImmutableErrType { private set }
CMethod? objTrap { private set }
CMethod? objWith { private set }
CMethod? objToImmutable { private set }
CMethod? boolNot { private set }
CMethod? intIncrement { private set }
CMethod? intDecrement { private set }
CMethod? intPlus { private set }
CMethod? floatPlus { private set }
CMethod? floatMinus { private set }
CMethod? strPlus { private set }
CMethod? strBufMake { private set }
CMethod? strBufAdd { private set }
CMethod? strBufToStr { private set }
CMethod? listMake { private set }
CMethod? listMakeObj { private set }
CMethod? listAdd { private set }
CMethod? mapMake { private set }
CMethod? mapSet { private set }
CMethod? enumOrdinal { private set }
CMethod? funcBind { private set }
CMethod? rangeMakeInclusive { private set }
CMethod? rangeMakeExclusive { private set }
CMethod? slotFindMethod { private set }
CMethod? slotFindFunc { private set }
CMethod? podFind { private set }
CMethod? podLocale { private set }
CMethod? typePod { private set }
CMethod? typeField { private set }
CMethod? typeMethod { private set }
CMethod? funcEnterCtor { private set }
CMethod? funcExitCtor { private set }
CMethod? funcCheckInCtor { private set }
CMethod? funcCall { private set }
CMethod? fieldNotSetErrMake { private set }
CMethod? notImmutableErrMake { private set }
}