@@ -76,6 +76,7 @@ public class Compiler implements Opcodes{
7676
7777static final Keyword inlineKey = Keyword .intern (null , "inline" );
7878static final Keyword inlineAritiesKey = Keyword .intern (null , "inline-arities" );
79+ static final Keyword staticKey = Keyword .intern (null , "static" );
7980
8081static final Keyword volatileKey = Keyword .intern (null , "volatile" );
8182static final Keyword implementsKey = Keyword .intern (null , "implements" );
@@ -854,6 +855,15 @@ private static Class maybeClass(Object form, boolean stringOk) throws Exception{
854855 Object o = currentNS ().getMapping (sym );
855856 if (o instanceof Class )
856857 c = (Class ) o ;
858+ else
859+ {
860+ try {
861+ c = RT .classForName (sym .name );
862+ }
863+ catch (Exception e ){
864+ //aargh
865+ }
866+ }
857867 }
858868 }
859869 }
@@ -2808,8 +2818,8 @@ public boolean canEmitPrimitive(){
28082818 }
28092819
28102820 public void emitUnboxed (C context , ObjExpr objx , GeneratorAdapter gen ){
2811- expr .emit (C .EXPRESSION ,objx ,gen );
2812- gen .instanceOf (Type . getType (c ));
2821+ expr .emit (C .EXPRESSION , objx , gen );
2822+ gen .instanceOf (getType (c ));
28132823 }
28142824
28152825 public void emit (C context , ObjExpr objx , GeneratorAdapter gen ){
@@ -3154,7 +3164,9 @@ CONSTANT_IDS, new IdentityHashMap(),
31543164 //arglist might be preceded by symbol naming this fn
31553165 if (RT .second (form ) instanceof Symbol )
31563166 {
3157- fn .thisName = ((Symbol ) RT .second (form )).name ;
3167+ Symbol nm = (Symbol ) RT .second (form );
3168+ fn .thisName = nm .name ;
3169+ fn .isStatic = RT .booleanCast (RT .get (nm .meta (), staticKey ));
31583170 form = RT .cons (FN , RT .next (RT .next (form )));
31593171 }
31603172
@@ -3167,7 +3179,7 @@ CONSTANT_IDS, new IdentityHashMap(),
31673179 FnMethod variadicMethod = null ;
31683180 for (ISeq s = RT .next (form ); s != null ; s = RT .next (s ))
31693181 {
3170- FnMethod f = FnMethod .parse (fn , (ISeq ) RT .first (s ));
3182+ FnMethod f = FnMethod .parse (fn , (ISeq ) RT .first (s ), fn . isStatic );
31713183 if (f .isVariadic ())
31723184 {
31733185 if (variadicMethod == null )
@@ -3271,6 +3283,7 @@ static public class ObjExpr implements Expr{
32713283
32723284 final static Method voidctor = Method .getMethod ("void <init>()" );
32733285 protected IPersistentMap classMeta ;
3286+ protected boolean isStatic ;
32743287
32753288 public final String name (){
32763289 return name ;
@@ -4082,11 +4095,12 @@ private void emitLocal(GeneratorAdapter gen, LocalBinding lb, boolean clear){
40824095 }
40834096 else
40844097 {
4098+ int argoff = isStatic ?0 :1 ;
40854099 Class primc = lb .getPrimitiveType ();
40864100// String rep = lb.sym.name + " " + lb.toString().substring(lb.toString().lastIndexOf('@'));
40874101 if (lb .isArg )
40884102 {
4089- gen .loadArg (lb .idx -1 );
4103+ gen .loadArg (lb .idx -argoff );
40904104 if (primc != null )
40914105 HostExpr .emitBoxReturn (this , gen , primc );
40924106 else
@@ -4095,7 +4109,7 @@ private void emitLocal(GeneratorAdapter gen, LocalBinding lb, boolean clear){
40954109 {
40964110// System.out.println("clear: " + rep);
40974111 gen .visitInsn (Opcodes .ACONST_NULL );
4098- gen .storeArg (lb .idx - 1 );
4112+ gen .storeArg (lb .idx - argoff );
40994113 }
41004114 else
41014115 {
@@ -4129,14 +4143,15 @@ private void emitLocal(GeneratorAdapter gen, LocalBinding lb, boolean clear){
41294143 }
41304144
41314145 private void emitUnboxedLocal (GeneratorAdapter gen , LocalBinding lb ){
4146+ int argoff = isStatic ?0 :1 ;
41324147 Class primc = lb .getPrimitiveType ();
41334148 if (closes .containsKey (lb ))
41344149 {
41354150 gen .loadThis ();
41364151 gen .getField (objtype , lb .name , Type .getType (primc ));
41374152 }
41384153 else if (lb .isArg )
4139- gen .loadArg (lb .idx -1 );
4154+ gen .loadArg (lb .idx -argoff );
41404155 else
41414156 gen .visitVarInsn (Type .getType (primc ).getOpcode (Opcodes .ILOAD ), lb .idx );
41424157 }
@@ -4248,18 +4263,22 @@ public static class FnMethod extends ObjMethod{
42484263 //localbinding->localbinding
42494264 PersistentVector reqParms = PersistentVector .EMPTY ;
42504265 LocalBinding restParm = null ;
4266+ Type [] argtypes ;
4267+ Class [] argclasses ;
4268+ Class retClass ;
42514269
42524270 public FnMethod (ObjExpr objx , ObjMethod parent ){
42534271 super (objx , parent );
42544272 }
42554273
4256- static FnMethod parse (ObjExpr objx , ISeq form ) throws Exception {
4274+ static FnMethod parse (ObjExpr objx , ISeq form , boolean isStatic ) throws Exception {
42574275 //([args] body...)
42584276 IPersistentVector parms = (IPersistentVector ) RT .first (form );
42594277 ISeq body = RT .next (form );
42604278 try
42614279 {
42624280 FnMethod method = new FnMethod (objx , (ObjMethod ) METHOD .deref ());
4281+ method .retClass = tagClass (tagOf (parms ));
42634282 method .line = (Integer ) LINE .deref ();
42644283 //register as the current method and set up a new env frame
42654284 PathNode pnode = (PathNode ) CLEAR_PATH .get ();
@@ -4278,12 +4297,17 @@ static FnMethod parse(ObjExpr objx, ISeq form) throws Exception{
42784297
42794298 //register 'this' as local 0
42804299 //registerLocal(THISFN, null, null);
4281- if (objx .thisName != null )
4282- registerLocal (Symbol .intern (objx .thisName ), null , null ,false );
4283- else
4284- getAndIncLocalNum ();
4300+ if (!isStatic )
4301+ {
4302+ if (objx .thisName != null )
4303+ registerLocal (Symbol .intern (objx .thisName ), null , null ,false );
4304+ else
4305+ getAndIncLocalNum ();
4306+ }
42854307 PSTATE state = PSTATE .REQ ;
42864308 PersistentVector argLocals = PersistentVector .EMPTY ;
4309+ ArrayList <Type > argtypes = new ArrayList ();
4310+ ArrayList <Class > argclasses = new ArrayList ();
42874311 for (int i = 0 ; i < parms .count (); i ++)
42884312 {
42894313 if (!(parms .nth (i ) instanceof Symbol ))
@@ -4293,6 +4317,8 @@ static FnMethod parse(ObjExpr objx, ISeq form) throws Exception{
42934317 throw new Exception ("Can't use qualified name as parameter: " + p );
42944318 if (p .equals (_AMP_ ))
42954319 {
4320+ if (isStatic )
4321+ throw new Exception ("Variadic fns cannot be static" );
42964322 if (state == PSTATE .REQ )
42974323 state = PSTATE .REST ;
42984324 else
@@ -4301,7 +4327,14 @@ static FnMethod parse(ObjExpr objx, ISeq form) throws Exception{
43014327
43024328 else
43034329 {
4304- LocalBinding lb = registerLocal (p , state == PSTATE .REST ? ISEQ : tagOf (p ), null ,true );
4330+ Class pc = tagClass (tagOf (p ));
4331+ if (pc .isPrimitive () && !isStatic )
4332+ throw new Exception ("Non-static fn can't have primitive parameter: " + p );
4333+ argtypes .add (Type .getType (pc ));
4334+ argclasses .add (pc );
4335+ LocalBinding lb = isStatic ?
4336+ registerLocal (p ,null , new MethodParamExpr (pc ), true )
4337+ :registerLocal (p , state == PSTATE .REST ? ISEQ : tagOf (p ), null , true );
43054338 argLocals = argLocals .cons (lb );
43064339 switch (state )
43074340 {
@@ -4322,6 +4355,11 @@ static FnMethod parse(ObjExpr objx, ISeq form) throws Exception{
43224355 throw new Exception ("Can't specify more than " + MAX_POSITIONAL_ARITY + " params" );
43234356 LOOP_LOCALS .set (argLocals );
43244357 method .argLocals = argLocals ;
4358+ if (isStatic )
4359+ {
4360+ method .argtypes = argtypes .toArray (new Type [argtypes .size ()]);
4361+ method .argclasses = argclasses .toArray (new Class [argtypes .size ()]);
4362+ }
43254363 method .body = (new BodyExpr .Parser ()).parse (C .RETURN , body );
43264364 return method ;
43274365 }
@@ -4331,6 +4369,128 @@ static FnMethod parse(ObjExpr objx, ISeq form) throws Exception{
43314369 }
43324370 }
43334371
4372+ public void emit (ObjExpr fn , ClassVisitor cv ){
4373+ if (fn .isStatic )
4374+ doEmitStatic (fn ,cv );
4375+ else
4376+ doEmit (fn ,cv );
4377+ }
4378+
4379+ public void doEmitStatic (ObjExpr fn , ClassVisitor cv ){
4380+ Method ms = new Method ("invokeStatic" , getReturnType (), argtypes );
4381+
4382+ GeneratorAdapter gen = new GeneratorAdapter (ACC_PUBLIC + ACC_STATIC ,
4383+ ms ,
4384+ null ,
4385+ //todo don't hardwire this
4386+ EXCEPTION_TYPES ,
4387+ cv );
4388+ gen .visitCode ();
4389+ Label loopLabel = gen .mark ();
4390+ gen .visitLineNumber (line , loopLabel );
4391+ try
4392+ {
4393+ Var .pushThreadBindings (RT .map (LOOP_LABEL , loopLabel , METHOD , this ));
4394+ MaybePrimitiveExpr be = (MaybePrimitiveExpr ) body ;
4395+ if (Util .isPrimitive (retClass ) && be .canEmitPrimitive ())
4396+ {
4397+ if (be .getJavaClass () == retClass )
4398+ be .emitUnboxed (C .RETURN ,fn ,gen );
4399+ //todo - support the standard widening conversions
4400+ else
4401+ throw new IllegalArgumentException ("Mismatched primitive return, expected: "
4402+ + retClass + ", had: " + be .getJavaClass ());
4403+ }
4404+ else
4405+ {
4406+ body .emit (C .RETURN , fn , gen );
4407+ if (retClass == void .class )
4408+ {
4409+ gen .pop ();
4410+ }
4411+ else
4412+ gen .unbox (getReturnType ());
4413+ }
4414+ Label end = gen .mark ();
4415+ for (ISeq lbs = argLocals .seq (); lbs != null ; lbs = lbs .next ())
4416+ {
4417+ LocalBinding lb = (LocalBinding ) lbs .first ();
4418+ gen .visitLocalVariable (lb .name , argtypes [lb .idx ].getDescriptor (), null , loopLabel , end , lb .idx );
4419+ }
4420+ }
4421+ catch (Exception e )
4422+ {
4423+ throw new RuntimeException (e );
4424+ }
4425+ finally
4426+ {
4427+ Var .popThreadBindings ();
4428+ }
4429+
4430+ gen .returnValue ();
4431+ //gen.visitMaxs(1, 1);
4432+ gen .endMethod ();
4433+
4434+ //generate the regular invoke, calling the static method
4435+ Method m = new Method ("invoke" , OBJECT_TYPE , getArgTypes ());
4436+
4437+ gen = new GeneratorAdapter (ACC_PUBLIC ,
4438+ m ,
4439+ null ,
4440+ //todo don't hardwire this
4441+ EXCEPTION_TYPES ,
4442+ cv );
4443+ gen .visitCode ();
4444+ for (int i = 0 ; i < argtypes .length ; i ++)
4445+ {
4446+ gen .loadArg (i );
4447+ HostExpr .emitUnboxArg (fn , gen , argclasses [i ]);
4448+ }
4449+ gen .invokeStatic (objx .objtype , ms );
4450+ gen .box (getReturnType ());
4451+
4452+
4453+ gen .returnValue ();
4454+ //gen.visitMaxs(1, 1);
4455+ gen .endMethod ();
4456+
4457+ }
4458+
4459+ public void doEmit (ObjExpr fn , ClassVisitor cv ){
4460+ Method m = new Method (getMethodName (), getReturnType (), getArgTypes ());
4461+
4462+ GeneratorAdapter gen = new GeneratorAdapter (ACC_PUBLIC ,
4463+ m ,
4464+ null ,
4465+ //todo don't hardwire this
4466+ EXCEPTION_TYPES ,
4467+ cv );
4468+ gen .visitCode ();
4469+ Label loopLabel = gen .mark ();
4470+ gen .visitLineNumber (line , loopLabel );
4471+ try
4472+ {
4473+ Var .pushThreadBindings (RT .map (LOOP_LABEL , loopLabel , METHOD , this ));
4474+ body .emit (C .RETURN , fn , gen );
4475+ Label end = gen .mark ();
4476+
4477+ gen .visitLocalVariable ("this" , "Ljava/lang/Object;" , null , loopLabel , end , 0 );
4478+ for (ISeq lbs = argLocals .seq (); lbs != null ; lbs = lbs .next ())
4479+ {
4480+ LocalBinding lb = (LocalBinding ) lbs .first ();
4481+ gen .visitLocalVariable (lb .name , "Ljava/lang/Object;" , null , loopLabel , end , lb .idx );
4482+ }
4483+ }
4484+ finally
4485+ {
4486+ Var .popThreadBindings ();
4487+ }
4488+
4489+ gen .returnValue ();
4490+ //gen.visitMaxs(1, 1);
4491+ gen .endMethod ();
4492+ }
4493+
43344494 public final PersistentVector reqParms (){
43354495 return reqParms ;
43364496 }
@@ -4352,6 +4512,8 @@ String getMethodName(){
43524512 }
43534513
43544514 Type getReturnType (){
4515+ if (objx .isStatic )
4516+ return Type .getType (retClass );
43554517 return OBJECT_TYPE ;
43564518 }
43574519
@@ -5656,26 +5818,26 @@ else if(sym.name.indexOf('.') > 0 || sym.name.charAt(0) == '[')
56565818 }
56575819 else if (sym .equals (NS ))
56585820 return RT .NS_VAR ;
5659- else if (sym .equals (IN_NS ))
5660- return RT .IN_NS_VAR ;
5821+ else if (sym .equals (IN_NS ))
5822+ return RT .IN_NS_VAR ;
5823+ else
5824+ {
5825+ if (Util .equals (sym , COMPILE_STUB_SYM .get ()))
5826+ return COMPILE_STUB_CLASS .get ();
5827+ Object o = n .getMapping (sym );
5828+ if (o == null )
5829+ {
5830+ if (RT .booleanCast (RT .ALLOW_UNRESOLVED_VARS .deref ()))
5831+ {
5832+ return sym ;
5833+ }
56615834 else
56625835 {
5663- if (Util .equals (sym ,COMPILE_STUB_SYM .get ()))
5664- return COMPILE_STUB_CLASS .get ();
5665- Object o = n .getMapping (sym );
5666- if (o == null )
5667- {
5668- if (RT .booleanCast (RT .ALLOW_UNRESOLVED_VARS .deref ()))
5669- {
5670- return sym ;
5671- }
5672- else
5673- {
5674- throw new Exception ("Unable to resolve symbol: " + sym + " in this context" );
5675- }
5676- }
5677- return o ;
5836+ throw new Exception ("Unable to resolve symbol: " + sym + " in this context" );
56785837 }
5838+ }
5839+ return o ;
5840+ }
56795841}
56805842
56815843
0 commit comments