1 package kawa.standard; 2 import kawa.lang.*; 3 import gnu.lists.*; 4 import gnu.expr.*; 5 import gnu.math.IntNum; 6 import gnu.bytecode.*; 7 8 public class syntax_case extends Syntax 9 { 10 public static final syntax_case syntax_case = new syntax_case(); 11 static { syntax_case.setName("syntax-case"); } 12 13 PrimProcedure call_error; 14 15 Expression rewriteClauses (Object clauses, syntax_case_work work, 16 Translator tr) 17 { 18 Language language = tr.getLanguage(); 19 if (clauses == LList.Empty) 20 { 21 27 Expression[] args = new Expression[2]; 28 args[0] = new QuoteExp("syntax-case"); 29 args[1] = new ReferenceExp(work.inputExpression); 30 if (call_error == null) 31 { 32 ClassType clas = ClassType.make("kawa.standard.syntax_case"); 33 Type[] argtypes = new Type[2]; 34 argtypes[0] = Compilation.javaStringType; 35 argtypes[1] = Type.pointer_type; 36 Method method = clas.addMethod("error", argtypes, 37 Type.pointer_type, 38 Access.PUBLIC|Access.STATIC); 39 call_error = new PrimProcedure(method, language); 40 } 41 return new ApplyExp(call_error, args); 42 } 43 Object savePos = tr.pushPositionOf(clauses); 44 Object clause; 45 try 46 { 47 if (! (clauses instanceof Pair) 48 || ! ((clause = ((Pair) clauses).car) instanceof Pair)) 49 return tr.syntaxError("syntax-case: bad clause list"); 50 Pair pair = (Pair) clause; 51 PatternScope clauseScope = PatternScope.push(tr); 52 clauseScope.matchArray = tr.matchArray; 53 tr.push(clauseScope); 54 int outerVarCount = clauseScope.pattern_names.size(); 55 SyntaxPattern pattern 56 = new SyntaxPattern(pair.car, work.literal_identifiers, tr); 57 int varCount = pattern.varCount(); 58 if (varCount > work.maxVars) 59 work.maxVars = varCount; 60 61 BlockExp block = new BlockExp(); 62 Expression[] args = new Expression[4]; 63 args[0] = new QuoteExp(pattern); 64 args[1] = new ReferenceExp(work.inputExpression); 65 args[2] = new ReferenceExp(tr.matchArray); 66 args[3] = new QuoteExp(IntNum.zero()); 67 Expression tryMatch 68 = new ApplyExp(new PrimProcedure(Pattern.matchPatternMethod, language), args); 69 70 int newVarCount = varCount - outerVarCount; 71 Expression[] inits = new Expression[newVarCount]; 72 for (int i = newVarCount; --i >= 0; ) 73 inits[i] = QuoteExp.undefined_exp; 74 clauseScope.inits = inits; 75 76 Expression output; 77 SyntaxForm syntax = null; 78 Object tail = pair.cdr; 79 while (tail instanceof SyntaxForm) 80 { 81 syntax = (SyntaxForm) tail; 82 tail = syntax.form; 83 } 84 pair = (Pair) tail; 85 if (pair.cdr == LList.Empty) 86 output = tr.rewrite_car(pair, syntax); 87 else 88 { 89 Expression fender = tr.rewrite_car(pair, syntax); 90 if (! (pair.cdr instanceof Pair 91 && (pair = (Pair) pair.cdr).cdr == LList.Empty)) 92 return tr.syntaxError("syntax-case: bad clause"); 93 output = new IfExp(fender, tr.rewrite_car(pair, syntax), 94 new ExitExp(block)); 95 } 96 clauseScope.setBody(output); 97 98 tr.pop(clauseScope); 99 PatternScope.pop(tr); 100 block.setBody(new IfExp(tryMatch, clauseScope, new ExitExp(block)), 101 rewriteClauses(((Pair) clauses).cdr, work, tr)); 102 return block; 103 } 104 finally 105 { 106 tr.popPositionOf(savePos); 107 } 108 } 109 110 public Expression rewriteForm (Pair form, Translator tr) 111 { 112 syntax_case_work work = new syntax_case_work(); 113 114 Object obj = form.cdr; 115 if (obj instanceof Pair) 116 { 117 form = (Pair) obj; 118 Expression input = tr.rewrite(form.car); 119 obj = form.cdr; 120 if (obj instanceof Pair) 121 { 122 form = (Pair) obj; 123 work.literal_identifiers 124 = SyntaxPattern.getLiteralsList(form.car, null, tr); 125 obj = form.cdr; 126 127 Expression[] linits = new Expression[2]; 128 linits[0] = input; 129 LetExp let = new LetExp(linits); 130 work.inputExpression = let.addDeclaration((String ) null); 131 work.inputExpression.noteValue(linits[0]); 132 Declaration matchArrayOuter = tr.matchArray; 133 Declaration matchArray = let.addDeclaration((String ) null); 134 matchArray.setType(Compilation.objArrayType); 135 matchArray.setCanRead(true); 136 tr.matchArray = matchArray; 137 work.inputExpression.setCanRead(true); 138 tr.push(let); 139 let.body = rewriteClauses(obj, work, tr); 140 tr.pop(let); 141 142 Method allocVars = ClassType.make("kawa.lang.SyntaxPattern") 143 .getDeclaredMethod("allocVars", 2); 144 Expression[] args = new Expression[2]; 145 args[0] = new QuoteExp(IntNum.make(work.maxVars)); 146 if (matchArrayOuter == null) 147 args[1] = QuoteExp.nullExp; 148 else 149 args[1] = new ReferenceExp(matchArrayOuter); 150 linits[1] = new ApplyExp(allocVars, args); 151 matchArray.noteValue(linits[1]); 152 tr.matchArray = matchArrayOuter; 153 return let; 154 } 155 } 156 return tr.syntaxError("insufficiant arguments to syntax-case"); 157 } 158 159 160 public static Object error(String kind, Object arg) 161 { 162 Translator tr = (Translator) Compilation.getCurrent(); 163 if (tr == null) 164 throw new RuntimeException ("no match in syntax-case"); 165 Syntax syntax = tr.getCurrentSyntax(); 166 String name = syntax == null ? "some syntax" : syntax.getName(); 167 String msg = "no matching case while expanding " + name; 168 return tr.syntaxError(msg); 169 } 170 } 171 172 class syntax_case_work 173 { 174 LetExp let; 175 Object [] literal_identifiers; 176 177 178 Declaration inputExpression; 179 180 181 int maxVars; 182 } 183 | Popular Tags |