//
// Copyright (c) 2009, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 10 Jul 09 Andy Frank Creation
//
using compiler
**
** JsPod
**
class JsPod : JsNode
{
new make(JsCompilerSupport s, PodDef pod, TypeDef[] defs) : super(s)
{
this.name = pod.name
this.types = JsType[,]
this.props = JsProps[,]
// build native map
this.natives = Str:File[:]
s.compiler.jsFiles?.each |f| { natives[f.name] = f }
jsOutput := s.compiler.input.output === CompilerOutputMode.js
defs.each |TypeDef def|
{
// we inline closures directly, so no need to generate
// anonymous types like we do in Java and .NET
if (def.isClosure) return
// TODO FIXIT: do we still need this?
if (def.qname.contains("\$Cvars"))
{
echo("WARN: Cvar class: $def.qname")
return
}
// check for @js facet or explicit js output
if (def.hasFacet("sys::Js") || jsOutput)
types.add(JsType(s,def))
}
// resource files
baseDir := s.compiler.input.baseDir
if (baseDir != null)
{
s.compiler.resFiles.each |file|
{
uri := file.uri.relTo(baseDir.uri)
props.add(JsProps(pod, file, uri, s))
}
}
}
override Void write(JsWriter out)
{
// define namespace
out.w("fan.$name = {};").nl
// write types
types.each |t|
{
if (t.isNative) writePeer(out, t, false)
else
{
t.write(out)
if (t.hasNatives) writePeer(out, t, true)
}
}
// write type info
writeTypeInfo(out)
// write locale/en.props
p := props.find |p| { p.uri == `locale/en.props` }
p?.write(out)
// write static init
types.each |t| { t.writeStatic(out) }
// write remaining natives
natives.each |f|
{
in := f.in
out.minify(in)
in.close
}
}
Void writePeer(JsWriter out, JsType t, Bool isPeer)
{
key := isPeer ? "${t.peer.name}Peer.js" : "${t.name}.js"
file := natives[key]
if (file == null)
{
support.err("Missing native impl for $t.sig", Loc("${t.name}.fan"))
}
else
{
in := file.in
out.minify(in)
in.close
natives.remove(key)
}
}
Void writeTypeInfo(JsWriter out)
{
out.w("fan.${name}.\$pod = fan.sys.Pod.\$add('$name');").nl
out.w("with (fan.${name}.\$pod)").nl
out.w("{").nl
// filter out synthetic types from reflection
reflect := types.findAll |t| { !t.isSynthetic }
// write all types first
reflect.each |t|
{
adder := t.isMixin ? "\$am" : "\$at"
base := "$t.base.pod::$t.base.name"
mixins := t.mixins.join(",") |m| { "'$m.pod::$m.name'" }
facets := t.facets.join(",") |f| { "'$f.type.sig':$f.val.toCode" }
flags := t->flags
out.w(" fan.${t.pod}.${t.name}.\$type = $adder('$t.name','$base',[$mixins],{$facets},$flags);").nl
}
// then write slot info
reflect.each |t|
{
if (t.fields.isEmpty && t.methods.isEmpty) return
//out.w(" \$$i")
out.w(" fan.${t.pod}.${t.name}.\$type")
t.fields.each |f|
{
facets := f.facets.join(",") |x| { "'$x.type.sig':$x.val.toCode" }
out.w(".\$af('$f.origName',$f.flags,'$f.ftype.sig',{$facets})")
}
t.methods.each |m|
{
if (m.isFieldAccessor) return
params := m.params.join(",") |p| { "new fan.sys.Param('$p.name','$p.paramType.sig',$p.hasDef)" }
facets := m.facets.join(",") |f| { "'$f.type.sig':$f.val.toCode" }
out.w(".\$am('$m.origName',$m.flags,'$m.ret.sig',fan.sys.List.make(fan.sys.Param.\$type,[$params]),{$facets})")
}
out.w(";").nl
}
// end with block
out.w("}").nl
}
Str name // pod name
JsType[] types // types in this pod
Str:File natives // natives
JsProps[] props // prop files in this pod
}