public Expr Parse(ParserContext pcon, object form)
{
// (def x) or (def x initexpr) or (def x "docstring" initexpr)
string docstring = null;
if (RT.count(form) == 4 && (RT.third(form) is String))
{
docstring = (String)RT.third(form);
form = RT.list(RT.first(form), RT.second(form), RT.fourth(form));
}
if (RT.count(form) > 3)
throw new ParseException("Too many arguments to def");
if (RT.count(form) < 2)
throw new ParseException("Too few arguments to def");
Symbol sym = RT.second(form) as Symbol;
if (sym == null)
throw new ParseException("First argument to def must be a Symbol.");
//Console.WriteLine("Def {0}", sym.Name);
Var v = Compiler.LookupVar(sym, true);
if (v == null)
throw new ParseException("Can't refer to qualified var that doesn't exist");
if (!v.Namespace.Equals(Compiler.CurrentNamespace))
{
if (sym.Namespace == null)
v = Compiler.CurrentNamespace.intern(sym);
//throw new Exception(string.Format("Name conflict, can't def {0} because namespace: {1} refers to: {2}",
// sym, Compiler.CurrentNamespace.Name, v));
else
throw new ParseException("Can't create defs outside of current namespace");
}
IPersistentMap mm = sym.meta();
bool isDynamic = RT.booleanCast(RT.get(mm, Compiler.DynamicKeyword));
if (isDynamic)
v.setDynamic();
if (!isDynamic && sym.Name.StartsWith("*") && sym.Name.EndsWith("*") && sym.Name.Length > 1)
{
RT.errPrintWriter().WriteLine("Warning: {0} not declared dynamic and thus is not dynamically rebindable, "
+ "but its name suggests otherwise. Please either indicate ^:dynamic {0} or change the name.\n",
sym);
}
if (RT.booleanCast(RT.get(mm, Compiler.ArglistsKeyword)))
{
IPersistentMap vm = v.meta();
//vm = (IPersistentMap)RT.assoc(vm, Compiler.STATIC_KEY, true);
// drop quote
vm = (IPersistentMap)RT.assoc(vm, Compiler.ArglistsKeyword, RT.second(mm.valAt(Compiler.ArglistsKeyword)));
v.setMeta(vm);
}
Object source_path = Compiler.SourcePathVar.get();
source_path = source_path ?? "NO_SOURCE_FILE";
mm = (IPersistentMap)RT.assoc(mm,RT.LineKey, Compiler.LineVar.get())
.assoc(RT.FileKey, source_path);
//.assoc(RT.SOURCE_SPAN_KEY,Compiler.SOURCE_SPAN.deref());
if (docstring != null)
mm = (IPersistentMap)RT.assoc(mm, RT.DocKey, docstring);
//mm = mm.without(RT.DOC_KEY)
// .without(Keyword.intern(null, "arglists"))
// .without(RT.FILE_KEY)
// .without(RT.LINE_KEY)
// .without(Keyword.intern(null, "ns"))
// .without(Keyword.intern(null, "name"))
// .without(Keyword.intern(null, "added"))
// .without(Keyword.intern(null, "static"));
Expr meta = mm == null || mm.count() == 0 ? null : Compiler.Analyze(pcon.EvalOrExpr(),mm);
Expr init = Compiler.Analyze(pcon.EvalOrExpr(),RT.third(form), v.Symbol.Name);
bool initProvided = RT.count(form) == 3;
return new DefExpr(
(string)Compiler.SourceVar.deref(),
(int) Compiler.LineVar.deref(),
v, init, meta, initProvided,isDynamic);
}