From 2d385ac9c2a65547514c2c9061e8e2b4a837fd02 Mon Sep 17 00:00:00 2001 From: Richard Russo Date: Sun, 27 Jan 2019 13:56:28 -0800 Subject: [PATCH] initial project release --- LICENSE | 21 + README.md | 40 + bootstrap/.gitignore | 7 + bootstrap/bootstrap-ops-5.c | 81 + bootstrap/bootstrap-ops-5.h | 9 + bootstrap/bootstrap.h | 5 + bootstrap/tinyscheme-1.41/BUILDING | 139 + bootstrap/tinyscheme-1.41/CHANGES | 326 ++ bootstrap/tinyscheme-1.41/COPYING | 31 + bootstrap/tinyscheme-1.41/Manual.txt | 452 ++ .../tinyscheme-1.41/MiniSCHEMETribute.txt | 88 + bootstrap/tinyscheme-1.41/dynload.c | 146 + bootstrap/tinyscheme-1.41/dynload.h | 12 + bootstrap/tinyscheme-1.41/hack.txt | 244 + bootstrap/tinyscheme-1.41/init.scm | 716 +++ bootstrap/tinyscheme-1.41/makefile | 102 + bootstrap/tinyscheme-1.41/opdefines.h | 196 + bootstrap/tinyscheme-1.41/rm.cmd | 1 + bootstrap/tinyscheme-1.41/scheme-private.h | 211 + bootstrap/tinyscheme-1.41/scheme.c | 5143 +++++++++++++++++ bootstrap/tinyscheme-1.41/scheme.h | 255 + readme/Depend.md | 74 + readme/OldReadme.md | 249 + readme/SASM.md | 46 + readme/Status.md | 73 + readme/Tools.md | 39 + src/.gitignore | 5 + src/algo/bsearch.scm | 22 + src/algo/graph.scm | 127 + src/algo/hashtable.scm | 55 + src/algo/heapsort.scm | 82 + src/algo/lcs.scm | 20 + src/algo/quicksort.scm | 28 + src/algo/scc.scm | 53 + src/ast.scm | 283 + src/bootstrap.win32.makefile | 1347 +++++ src/build.scm | 142 + src/build/rules.scm | 123 + src/buildtags.sh | 10 + src/codegen.scm | 876 +++ src/compat/tinyscheme.scm | 107 + src/csharp-compiler.scm | 97 + src/csharp-grammar.scm | 736 +++ src/csharp-parser.scm | 5 + src/csharp-scanner.scm | 4 + src/csharp-tokens.scm | 127 + src/env-selfbld.cmd | 4 + src/env.cmd | 10 + src/fix-spimout.scm | 16 + src/generate-java-lexer.scm | 27 + src/go.cmd | 37 + src/java-compiler-ts.scm | 8 + src/java-compiler.dep | 33 + src/java-compiler.scm | 103 + src/lexer.scm | 38 + src/minijava-grammar.scm | 1193 ++++ src/minijava-lexer-java.scm | 4 + src/minijava-lexer.scm | 4 + src/minijava-parser.scm | 6 + src/minijava-tokens-java.scm | 238 + src/minijava-tokens.scm | 242 + src/need-test.scm | 3 + src/need.scm | 24 + src/needc-ts.scm | 2 + src/needc.scm | 549 ++ src/parse/genparse.scm | 508 ++ src/parse/parse.scm | 104 + src/parser.scm | 11 + src/pat/pat.scm | 185 + src/pretty.scm | 203 + src/read-expanded-format.scm | 61 + src/regex/compile.scm | 181 + src/regex/dfa.scm | 266 + src/regex/fast-dfa.scm | 229 + src/regex/fsm.scm | 15 + src/regex/genlex.scm | 71 + src/regex/nfa.scm | 325 ++ src/regex/regex.scm | 173 + src/repl.scm | 2 + src/rtl/CsharpRtl.cs | 57 + src/rtl/JavaRtl.java | 57 + src/rtl/c-rtlheap.sasm | 147 + src/rtl/debug.asm | 289 + src/rtl/gc-defines.sasm | 17 + src/rtl/gc-externs.sasm | 16 + src/rtl/gc-invoke.sasm | 20 + src/rtl/gc-mark-array.sasm | 61 + src/rtl/gc-mark-class.sasm | 48 + src/rtl/gc-mark-range.sasm | 48 + src/rtl/gc-mark.sasm | 203 + src/rtl/gc-stack.sasm | 60 + src/rtl/gc-sweep.sasm | 36 + src/rtl/gc-wrapper.sasm | 97 + src/rtl/gc.sasm | 96 + src/rtl/gctest.sasm | 43 + src/rtl/get-percents.scm | 26 + src/rtl/heap.sasm | 466 ++ src/rtl/heapfixed-debug.sasm | 352 ++ src/rtl/heapfixed.sasm | 352 ++ src/rtl/heaptest.sasm | 208 + src/rtl/heapvar.sasm | 495 ++ src/rtl/interp-rtlheap.sasm | 197 + src/rtl/makefile | 14 + src/rtl/mjrtl-spim.sasm | 39 + src/rtl/mjrtl.c | 103 + src/rtl/mjrtl.sasm | 15 + src/rtl/mm-param.sasm | 54 + src/rtl/nonexports.scm | 22 + src/rtl/r5rs-library.scm | 866 +++ src/rtl/r5rs-native.scm | 1203 ++++ src/rtl/r5rs-syntax.scm | 206 + src/rtl/r5rs-wrap.scm | 502 ++ src/rtl/rtlheap.sasm | 162 + src/rtl/rtlscheme.c | 178 + src/rtl/rtlscheme.sasm | 499 ++ src/rtl/sasm.h | 28 + src/rtl/scheme-main.sasm | 17 + src/rtl/scheme.java | 1015 ++++ src/rtl/scheme.javap | 1100 ++++ src/rtl/spim-main.s | 28 + src/run-ts.scm | 14 + src/sasm-interp-mips.scm | 8 + src/sasm-interp-ts.scm | 3 + src/sasm-interp-x86.scm | 8 + src/sasm-interp.scm | 1 + src/sasm-mips.scm | 5 + src/sasm-opt-mips.scm | 10 + src/sasm-opt-ts.scm | 3 + src/sasm-opt.dep | 79 + src/sasm-opt.scm | 21 + src/sasm-ts.scm | 3 + src/sasm-util.scm | 75 + src/sasm.dep | 79 + src/sasm.scm | 5 + src/sasm/fastgraph.scm | 23 + src/sasm/fastset.scm | 109 + src/sasm/fp.scm | 36 + src/sasm/machdesc.scm | 41 + src/sasm/nasmx86/arithmetic.scm | 26 + src/sasm/nasmx86/base.scm | 20 + src/sasm/nasmx86/binop.scm | 98 + src/sasm/nasmx86/bitwise-const.scm | 20 + src/sasm/nasmx86/call.scm | 25 + src/sasm/nasmx86/compare.scm | 46 + src/sasm/nasmx86/control.scm | 66 + src/sasm/nasmx86/data.scm | 19 + src/sasm/nasmx86/debug.scm | 8 + src/sasm/nasmx86/interp.scm | 40 + src/sasm/nasmx86/labels.scm | 12 + src/sasm/nasmx86/load-array.scm | 37 + src/sasm/nasmx86/machine.scm | 8 + src/sasm/nasmx86/mul.scm | 56 + src/sasm/nasmx86/preamble.scm | 31 + src/sasm/nasmx86/return.scm | 32 + src/sasm/nasmx86/shift.scm | 46 + src/sasm/nasmx86/stack.scm | 29 + src/sasm/nasmx86/store-array.scm | 71 + src/sasm/nasmx86/util.scm | 46 + src/sasm/parse/constant-operand.scm | 29 + src/sasm/parse/data-entry.scm | 40 + src/sasm/parse/extern.scm | 125 + src/sasm/parse/instruction.scm | 163 + src/sasm/parse/lvalue-operand.scm | 39 + src/sasm/parse/member.scm | 19 + src/sasm/parse/operand.scm | 41 + src/sasm/parse/operation.scm | 18 + src/sasm/parse/program.scm | 15 + src/sasm/parse/register-operand.scm | 33 + src/sasm/parse/statement.scm | 93 + src/sasm/parse/symconst-entry.scm | 20 + src/sasm/parse/syntax.scm | 33 + src/sasm/parse/util.scm | 16 + src/sasm/sasm-analyze.scm | 247 + src/sasm/sasm-ast.scm | 292 + src/sasm/sasm-codegen.scm | 45 + src/sasm/sasm-core.scm | 200 + src/sasm/sasm-dataflow.scm | 1185 ++++ src/sasm/sasm-eval.scm | 421 ++ src/sasm/sasm-insel.scm | 205 + src/sasm/sasm-insn.scm | 310 + src/sasm/sasm-interp-spec.scm | 43 + src/sasm/sasm-interp.scm | 1033 ++++ src/sasm/sasm-machine.scm | 611 ++ src/sasm/sasm-mips.scm | 343 ++ src/sasm/sasm-msil.scm | 19 + src/sasm/sasm-nasmx86.scm | 37 + src/sasm/sasm-opt.scm | 145 + src/sasm/sasm-parse.scm | 19 + src/sasm/sasm-regalloc.scm | 669 +++ src/sasm/sasm-rewrite.scm | 244 + src/sasm/sasm-tracing.scm | 61 + src/sasm/sasm-tx.scm | 25 + src/sasm/sasm-visitor.scm | 386 ++ src/sasm/sasm.scm | 52 + src/sasm/tx/assemble.scm | 50 + src/sasm/tx/config.scm | 19 + src/sasm/tx/context.scm | 6 + src/sasm/tx/emit.scm | 21 + src/sasm/tx/globals.scm | 5 + src/sasm/tx/interp.scm | 8 + src/sasm/tx/labels.scm | 30 + src/sasm/tx/main.scm | 47 + src/sasm/tx/read.scm | 21 + src/sasm/tx/registers.scm | 41 + src/sasm/tx/regrule.scm | 99 + src/sasm/tx/rewrite.scm | 46 + src/sasm/tx/stmt.scm | 53 + src/sasm/tx/symconst.scm | 23 + src/sasm/tx/util.scm | 6 + src/scheme-compiler-ts.scm | 7 + src/scheme-compiler.dep | 53 + src/scheme-compiler.scm | 462 ++ src/scheme-gluec-ts.scm | 5 + src/scheme-gluec.scm | 166 + src/scheme-interpreter-ts.scm | 6 + src/scheme-interpreter.scm | 138 + src/scheme/base-syntax.scm | 142 + src/scheme/compiler/codegen.scm | 182 + src/scheme/compiler/codegen/application.scm | 80 + src/scheme/compiler/codegen/emit.scm | 82 + src/scheme/compiler/codegen/epilogue.scm | 80 + src/scheme/compiler/codegen/immediate.scm | 79 + src/scheme/compiler/codegen/lambda.scm | 204 + src/scheme/compiler/codegen/letrec.scm | 40 + src/scheme/compiler/codegen/pretty-print.scm | 4 + src/scheme/compiler/codegen/reference.scm | 44 + src/scheme/compiler/codegen/set.scm | 58 + src/scheme/compiler/codegen/tailcall.scm | 32 + src/scheme/compiler/codegen/targets.scm | 18 + src/scheme/compiler/context.scm | 48 + src/scheme/compiler/cps.scm | 14 + src/scheme/compiler/env.scm | 10 + src/scheme/compiler/gc.scm | 78 + src/scheme/compiler/labels.scm | 56 + src/scheme/compiler/linkage.scm | 39 + src/scheme/compiler/settings.scm | 12 + src/scheme/genproc.scm | 52 + src/scheme/meta-eval.scm | 590 ++ src/scheme/syntax/core.scm | 83 + src/scheme/syntax/core/context.scm | 31 + src/scheme/syntax/core/env.scm | 28 + src/scheme/syntax/core/expand.scm | 136 + src/scheme/syntax/core/macro.scm | 115 + src/scheme/syntax/core/reference.scm | 13 + src/scheme/syntax/core/specform.scm | 10 + src/scheme/syntax/expand-context.scm | 22 + src/scheme/syntax/expander.scm | 6 + src/scheme/syntax/specform.scm | 160 + src/scheme/syntax/syntax.scm | 280 + src/scheme/tag.scm | 43 + src/scheme/transforms/cps.scm | 114 + src/scheme/transforms/internal-defines.scm | 42 + .../frontend/java/ast/ArrayTypeSpecifier.java | 16 + src/scp/frontend/java/ast/ClassBody.java | 25 + src/scp/frontend/java/ast/ClassList.java | 44 + src/scp/frontend/java/ast/ClassPart.java | 7 + src/scp/frontend/java/ast/ClassParts.java | 53 + .../frontend/java/ast/FieldDefinition.java | 32 + src/scp/frontend/java/ast/MainClass.java | 33 + .../frontend/java/ast/MethodAttributes.java | 13 + src/scp/frontend/java/ast/MethodBody.java | 14 + .../frontend/java/ast/MethodDefinition.java | 20 + src/scp/frontend/java/ast/Node.java | 5 + src/scp/frontend/java/ast/Parameter.java | 16 + src/scp/frontend/java/ast/ParameterList.java | 51 + src/scp/frontend/java/ast/Program.java | 16 + .../java/ast/SimpleTypeSpecifier.java | 19 + src/scp/frontend/java/ast/Statement.java | 4 + src/scp/frontend/java/ast/StatementBlock.java | 35 + .../java/ast/StaticFieldDefinition.java | 15 + src/scp/frontend/java/ast/TypeSpecifier.java | 9 + .../frontend/java/ast/VariableDefinition.java | 22 + .../java/ast/VariableDefinitionBlock.java | 35 + src/scp/frontend/java/ast/Visitor.java | 7 + src/scp/frontend/java/ast/_Class.java | 25 + .../frontend/java/lexer/AdjacencyRule.java | 97 + .../frontend/java/lexer/JavaLexerData.java | 1720 ++++++ src/scp/frontend/java/lexer/Lexer.java | 91 + src/scp/frontend/java/lexer/LexerTest.java | 83 + src/scp/frontend/java/lexer/Token.java | 23 + src/scp/frontend/java/lexer/TokenType.java | 84 + src/selfbld.win32.makefile | 930 +++ src/smake-grammar.scm | 167 + src/smake-lexer-test.scm | 43 + src/smake-lexer.scm | 4 + src/smake-parser.scm | 5 + src/smake-tokens.scm | 200 + src/smake.scm | 36 + src/spim-makefile | 5 + src/symtab.scm | 68 + src/tailcall.scm | 123 + src/tests.makefile | 141 + src/tests.win32.makefile | 206 + src/tests/Arrays.java | 28 + src/tests/BinarySearch.java | 151 + src/tests/BinaryTree.java | 334 ++ src/tests/Bitwise.java | 60 + src/tests/BubbleSort.java | 95 + src/tests/CharString.java | 42 + src/tests/Count.java | 23 + src/tests/CtorTest.java | 22 + src/tests/Factorial.java | 18 + src/tests/LinearSearch.java | 99 + src/tests/LinkedList.java | 289 + src/tests/Messy.java | 16 + src/tests/MyFactorial.java | 31 + src/tests/NumberToString.java | 106 + src/tests/ObjArray.java | 31 + src/tests/OpEquals.java | 42 + src/tests/OverrideTest.java | 28 + src/tests/QuickSort.java | 112 + src/tests/Rectangles.java | 177 + src/tests/StaticMembers.java | 27 + src/tests/StaticMethods.java | 20 + src/tests/SubExp.java | 60 + src/tests/TreeVisitor.java | 397 ++ src/tests/TwoArgs.java | 28 + src/tests/apply.scm | 1 + src/tests/argv.scm | 14 + src/tests/badapply.cmd | 2 + src/tests/badapply.scm | 4 + src/tests/badsrhi.cmd | 7 + src/tests/badsrhi.scm | 3 + src/tests/badsrlo.cmd | 7 + src/tests/badsrlo.scm | 3 + src/tests/badsshi.cmd | 7 + src/tests/badsshi.scm | 3 + src/tests/badsslo.cmd | 7 + src/tests/badsslo.scm | 3 + src/tests/badvrhi.cmd | 7 + src/tests/badvrhi.scm | 3 + src/tests/badvrlo.cmd | 7 + src/tests/badvrlo.scm | 3 + src/tests/badvshi.cmd | 7 + src/tests/badvshi.scm | 3 + src/tests/badvslo.cmd | 7 + src/tests/badvslo.scm | 3 + src/tests/baseline/Arrays.actual | 34 + src/tests/baseline/BinarySearch.actual | 173 + src/tests/baseline/BinaryTree.actual | 26 + src/tests/baseline/Bitwise.actual | 155 + src/tests/baseline/BubbleSort.actual | 22 + src/tests/baseline/CharString.actual | 3 + src/tests/baseline/Count.actual | 1 + src/tests/baseline/CtorTest.actual | 3 + src/tests/baseline/Factorial.actual | 1 + src/tests/baseline/GCStress-gc.actual | 513 ++ src/tests/baseline/GCStress2-gc.actual | 2305 ++++++++ src/tests/baseline/GCTest1-gc.actual | 8 + src/tests/baseline/LinearSearch.actual | 15 + src/tests/baseline/LinkedList.actual | 47 + src/tests/baseline/Messy.actual | 1 + src/tests/baseline/MyFactorial.actual | 1 + src/tests/baseline/NumberToString.actual | 28 + src/tests/baseline/ObjArray.actual | 1 + src/tests/baseline/OpEquals.actual | 1 + src/tests/baseline/OverrideTest.actual | 1 + src/tests/baseline/QuickSort.actual | 22 + src/tests/baseline/Rectangles.actual | 109 + src/tests/baseline/Speed-perf.actual | 1 + src/tests/baseline/Speed2-perf.actual | 1 + src/tests/baseline/StaticMembers.actual | 1 + src/tests/baseline/StaticMethods.actual | 1 + src/tests/baseline/SubExp.actual | 1 + src/tests/baseline/TreeVisitor.actual | 86 + src/tests/baseline/TwoArgs.actual | 3 + src/tests/baseline/apply-s.actual | 1 + src/tests/baseline/argv-s.actual | 13 + src/tests/baseline/badapply-s.actual | 1 + src/tests/baseline/badsrhi-s.actual | 2 + src/tests/baseline/badsrlo-s.actual | 2 + src/tests/baseline/badsshi-s.actual | 2 + src/tests/baseline/badsslo-s.actual | 2 + src/tests/baseline/badvrhi-s.actual | 2 + src/tests/baseline/badvrlo-s.actual | 2 + src/tests/baseline/badvshi-s.actual | 2 + src/tests/baseline/badvslo-s.actual | 2 + src/tests/baseline/call.sasm-interp.actual | 1 + src/tests/baseline/call.sasm-util.actual | 32 + src/tests/baseline/char-case-s.actual | 51 + src/tests/baseline/char-s.actual | 62 + src/tests/baseline/const-s.actual | 0 src/tests/baseline/const2-s.actual | 1 + src/tests/baseline/count-s.actual | 1 + src/tests/baseline/delete-s.actual | 1 + src/tests/baseline/disp1-s.actual | 1 + src/tests/baseline/disp2-s.actual | 1 + src/tests/baseline/disptest-s.actual | 23 + src/tests/baseline/disptest2-s.actual | 5 + src/tests/baseline/eq-s.actual | 9 + src/tests/baseline/equal-s.actual | 36 + src/tests/baseline/eqv-s.actual | 31 + src/tests/baseline/factorial-s.actual | 1 + src/tests/baseline/factorial2-s.actual | 1 + src/tests/baseline/fastset-unittest.actual | 0 src/tests/baseline/gc-test.sasm-interp.actual | 0 src/tests/baseline/gc-test.sasm-util.actual | 22 + src/tests/baseline/genparse-unittest.actual | 36 + src/tests/baseline/genproc-unittest.actual | 3 + src/tests/baseline/getenv-s.actual | 2 + src/tests/baseline/hw-s.actual | 1 + src/tests/baseline/hw2-s.actual | 1 + src/tests/baseline/hw3-s.actual | 3 + src/tests/baseline/implambda-s.actual | 10 + src/tests/baseline/inputfile-s.actual | 22 + src/tests/baseline/lambda1-s.actual | 1 + src/tests/baseline/list-s.actual | 1 + src/tests/baseline/list-unittest.actual | 1 + .../mjrtl-mips-test.sasm-interp.actual | 1 + .../baseline/mjrtl-mips-test.sasm-util.actual | 25 + src/tests/baseline/mkstring-s.actual | 12 + src/tests/baseline/mkvec-s.actual | 7 + src/tests/baseline/modquot-s.actual | 12 + src/tests/baseline/mul-s.actual | 1 + src/tests/baseline/n2s-s.actual | 4 + src/tests/baseline/nest.sasm-interp.actual | 2 + src/tests/baseline/nest.sasm-util.actual | 21 + src/tests/baseline/num2str-s.actual | 5 + src/tests/baseline/opdiv-s.actual | 36 + src/tests/baseline/opeq-s.actual | 27 + src/tests/baseline/opgt-s.actual | 39 + src/tests/baseline/oplt-s.actual | 54 + src/tests/baseline/opminus-s.actual | 18 + src/tests/baseline/opmul-s.actual | 15 + src/tests/baseline/opplus-s.actual | 18 + src/tests/baseline/order-eval-s.actual | 4 + src/tests/baseline/outputfile-s.actual | 2 + src/tests/baseline/outputfile.dat | 2 + src/tests/baseline/pair-s.actual | 30 + src/tests/baseline/pat-unittest.actual | 31 + src/tests/baseline/peekchar-s.actual | 2 + src/tests/baseline/pred-s.actual | 2 + src/tests/baseline/r5rs1-s.actual | 81 + src/tests/baseline/r5rs2-s.actual | 54 + src/tests/baseline/r5rs3-s.actual | 33 + src/tests/baseline/read-s.actual | 29 + src/tests/baseline/read10-s.actual | 17 + src/tests/baseline/read11-s.actual | 8 + src/tests/baseline/read2-s.actual | 16 + src/tests/baseline/read3-s.actual | 3 + src/tests/baseline/read4-s.actual | 19 + src/tests/baseline/read5-s.actual | 1 + src/tests/baseline/read6-s.actual | 21 + src/tests/baseline/read7-s.actual | 8 + src/tests/baseline/read8-s.actual | 4 + src/tests/baseline/read9-s.actual | 18 + src/tests/baseline/regex-unittest.actual | 11 + src/tests/baseline/rename-s.actual | 1 + src/tests/baseline/sasm-insn-unittest.actual | 18 + src/tests/baseline/scm1-s.actual | 1 + src/tests/baseline/set1-s.actual | 3 + src/tests/baseline/stat-s.actual | 7 + src/tests/baseline/str2num-s.actual | 51 + src/tests/baseline/str2num2-s.actual | 10 + src/tests/baseline/string-s.actual | 42 + src/tests/baseline/string2-s.actual | 48 + src/tests/baseline/string3-s.actual | 51 + src/tests/baseline/stringset-s.actual | 2 + src/tests/baseline/strref-s.actual | 1 + src/tests/baseline/sum-s.actual | 20 + src/tests/baseline/sym1-s.actual | 5 + src/tests/baseline/temp.sasm-interp.actual | 3 + src/tests/baseline/temp.sasm-util.actual | 26 + src/tests/baseline/test-read-s.actual | 2 + src/tests/baseline/test-s.actual | 1 + src/tests/baseline/test1-cs.actual | 1 + src/tests/baseline/test2-cs.actual | 1 + src/tests/baseline/vararg-s.actual | 1 + src/tests/baseline/wc-s.actual | 1 + src/tests/baseline/write-s.actual | 25 + src/tests/call.sasm | 28 + src/tests/char-case.scm | 33 + src/tests/char.scm | 35 + src/tests/const.scm | 4 + src/tests/const2.scm | 3 + src/tests/count.scm | 8 + src/tests/cseconds.scm | 13 + src/tests/delete.scm | 2 + src/tests/disp1.scm | 1 + src/tests/disp2.scm | 2 + src/tests/disptest.scm | 107 + src/tests/disptest2.scm | 10 + src/tests/eq.scm | 18 + src/tests/equal.scm | 27 + src/tests/eqv.scm | 74 + src/tests/factorial.scm | 7 + src/tests/factorial2.scm | 7 + src/tests/fastset.ss | 13 + src/tests/gc-test.sasm | 17 + src/tests/gc/GCStress.java | 74 + src/tests/gc/GCStress2.java | 76 + src/tests/gc/GCStress3.java | 40 + src/tests/gc/GCTest1.java | 35 + src/tests/gc/GCTest2.java | 42 + src/tests/gc/GCTest3.java | 68 + src/tests/gc/GCTest4.java | 68 + src/tests/gc1.scm | 25 + src/tests/genparse.ss | 19 + src/tests/genproc.ss | 18 + src/tests/getenv.scm | 4 + src/tests/hw.scm | 2 + src/tests/hw2.scm | 4 + src/tests/hw3.scm | 11 + src/tests/if.scm | 5 + src/tests/implambda.scm | 13 + src/tests/inputfile.scm | 17 + src/tests/lambda1.scm | 5 + src/tests/letrec.scm | 9 + src/tests/list.scm | 4 + src/tests/list.ss | 4 + src/tests/mjrtl-mips-test.sasm | 22 + src/tests/mkstring.scm | 24 + src/tests/mkvec.scm | 26 + src/tests/modquot.scm | 27 + src/tests/mul.scm | 2 + src/tests/n2s.scm | 8 + src/tests/neg/GCTest2.java | 29 + src/tests/neg/Speed.java | 59 + src/tests/nest.sasm | 16 + src/tests/num2str.scm | 52 + src/tests/opdiv.scm | 27 + src/tests/opeq.scm | 24 + src/tests/opgt.scm | 28 + src/tests/oplt.scm | 33 + src/tests/opminus.scm | 21 + src/tests/opmul.scm | 20 + src/tests/opplus.scm | 21 + src/tests/order-eval.scm | 17 + src/tests/outputfile.scm | 10 + src/tests/pair.scm | 27 + src/tests/pat.ss | 135 + src/tests/peekchar.scm | 16 + src/tests/perf/Speed.java | 56 + src/tests/perf/Speed2.java | 94 + src/tests/pred.scm | 10 + src/tests/printer-helper.scm | 1 + src/tests/printer.scm | 10 + src/tests/quot.scm | 32 + src/tests/r5rs1.scm | 42 + src/tests/r5rs2.scm | 33 + src/tests/r5rs3.scm | 38 + src/tests/read-dat-imp.scm | 1 + src/tests/read-dat.scm | 1 + src/tests/read-dat2.scm | 51 + src/tests/read-dat3.scm | 1 + src/tests/read-dat4.scm | 28 + src/tests/read-escapes.scm | 1 + src/tests/read-ext-id.scm | 1 + src/tests/read-namedchar.scm | 1 + src/tests/read.scm | 192 + src/tests/read10.scm | 13 + src/tests/read11.scm | 13 + src/tests/read2.scm | 45 + src/tests/read3.scm | 9 + src/tests/read4.scm | 7 + src/tests/read5.scm | 7 + src/tests/read6.scm | 96 + src/tests/read7.scm | 178 + src/tests/read8.scm | 18 + src/tests/read9.scm | 16 + src/tests/regex.ss | 28 + src/tests/rename.scm | 2 + src/tests/sasm-insn.ss | 24 + src/tests/sasm1.scm | 64 + src/tests/scm1.scm | 10 + src/tests/set1.scm | 12 + src/tests/smake-test.txt | 11 + src/tests/stat-dat.scm | 1 + src/tests/stat.scm | 16 + src/tests/str2num.scm | 32 + src/tests/str2num2.scm | 40 + src/tests/string.scm | 30 + src/tests/string2.scm | 31 + src/tests/string3.scm | 33 + src/tests/stringset.scm | 10 + src/tests/strref.scm | 1 + src/tests/sum.scm | 55 + src/tests/sym1.scm | 15 + src/tests/syntax1.scm | 11 + src/tests/syntax1.syn | 11 + src/tests/syntax2.scm | 4 + src/tests/temp.sasm | 20 + src/tests/test-read.scm | 10 + src/tests/test.scm | 5 + src/tests/test1.cs | 23 + src/tests/test2.cs | 20 + src/tests/vararg.scm | 7 + src/tests/wc.scm | 1 + src/tests/write.scm | 23 + src/typechk.scm | 342 ++ src/types.scm | 471 ++ src/util/counting.scm | 28 + src/util/filesystem.scm | 51 + src/util/format.scm | 43 + src/util/io.scm | 61 + src/util/list.scm | 278 + src/util/matrix.scm | 19 + src/util/output-file.scm | 54 + src/util/readhelp.scm | 19 + src/util/rfilact.scm | 4 + src/util/string.scm | 295 + src/util/symbol.scm | 7 + src/util/vector.scm | 72 + 603 files changed, 56879 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 bootstrap/.gitignore create mode 100644 bootstrap/bootstrap-ops-5.c create mode 100644 bootstrap/bootstrap-ops-5.h create mode 100644 bootstrap/bootstrap.h create mode 100644 bootstrap/tinyscheme-1.41/BUILDING create mode 100644 bootstrap/tinyscheme-1.41/CHANGES create mode 100644 bootstrap/tinyscheme-1.41/COPYING create mode 100644 bootstrap/tinyscheme-1.41/Manual.txt create mode 100644 bootstrap/tinyscheme-1.41/MiniSCHEMETribute.txt create mode 100644 bootstrap/tinyscheme-1.41/dynload.c create mode 100644 bootstrap/tinyscheme-1.41/dynload.h create mode 100644 bootstrap/tinyscheme-1.41/hack.txt create mode 100644 bootstrap/tinyscheme-1.41/init.scm create mode 100644 bootstrap/tinyscheme-1.41/makefile create mode 100644 bootstrap/tinyscheme-1.41/opdefines.h create mode 100644 bootstrap/tinyscheme-1.41/rm.cmd create mode 100644 bootstrap/tinyscheme-1.41/scheme-private.h create mode 100644 bootstrap/tinyscheme-1.41/scheme.c create mode 100644 bootstrap/tinyscheme-1.41/scheme.h create mode 100644 readme/Depend.md create mode 100644 readme/OldReadme.md create mode 100644 readme/SASM.md create mode 100644 readme/Status.md create mode 100644 readme/Tools.md create mode 100644 src/.gitignore create mode 100644 src/algo/bsearch.scm create mode 100644 src/algo/graph.scm create mode 100644 src/algo/hashtable.scm create mode 100644 src/algo/heapsort.scm create mode 100644 src/algo/lcs.scm create mode 100644 src/algo/quicksort.scm create mode 100644 src/algo/scc.scm create mode 100644 src/ast.scm create mode 100644 src/bootstrap.win32.makefile create mode 100644 src/build.scm create mode 100644 src/build/rules.scm create mode 100644 src/buildtags.sh create mode 100644 src/codegen.scm create mode 100644 src/compat/tinyscheme.scm create mode 100644 src/csharp-compiler.scm create mode 100644 src/csharp-grammar.scm create mode 100644 src/csharp-parser.scm create mode 100644 src/csharp-scanner.scm create mode 100644 src/csharp-tokens.scm create mode 100644 src/env-selfbld.cmd create mode 100644 src/env.cmd create mode 100644 src/fix-spimout.scm create mode 100644 src/generate-java-lexer.scm create mode 100644 src/go.cmd create mode 100644 src/java-compiler-ts.scm create mode 100644 src/java-compiler.dep create mode 100644 src/java-compiler.scm create mode 100644 src/lexer.scm create mode 100644 src/minijava-grammar.scm create mode 100644 src/minijava-lexer-java.scm create mode 100644 src/minijava-lexer.scm create mode 100644 src/minijava-parser.scm create mode 100644 src/minijava-tokens-java.scm create mode 100644 src/minijava-tokens.scm create mode 100644 src/need-test.scm create mode 100644 src/need.scm create mode 100644 src/needc-ts.scm create mode 100644 src/needc.scm create mode 100644 src/parse/genparse.scm create mode 100644 src/parse/parse.scm create mode 100644 src/parser.scm create mode 100644 src/pat/pat.scm create mode 100644 src/pretty.scm create mode 100644 src/read-expanded-format.scm create mode 100644 src/regex/compile.scm create mode 100644 src/regex/dfa.scm create mode 100644 src/regex/fast-dfa.scm create mode 100644 src/regex/fsm.scm create mode 100644 src/regex/genlex.scm create mode 100644 src/regex/nfa.scm create mode 100644 src/regex/regex.scm create mode 100644 src/repl.scm create mode 100644 src/rtl/CsharpRtl.cs create mode 100644 src/rtl/JavaRtl.java create mode 100644 src/rtl/c-rtlheap.sasm create mode 100644 src/rtl/debug.asm create mode 100644 src/rtl/gc-defines.sasm create mode 100644 src/rtl/gc-externs.sasm create mode 100644 src/rtl/gc-invoke.sasm create mode 100644 src/rtl/gc-mark-array.sasm create mode 100644 src/rtl/gc-mark-class.sasm create mode 100644 src/rtl/gc-mark-range.sasm create mode 100644 src/rtl/gc-mark.sasm create mode 100644 src/rtl/gc-stack.sasm create mode 100644 src/rtl/gc-sweep.sasm create mode 100644 src/rtl/gc-wrapper.sasm create mode 100644 src/rtl/gc.sasm create mode 100644 src/rtl/gctest.sasm create mode 100644 src/rtl/get-percents.scm create mode 100644 src/rtl/heap.sasm create mode 100644 src/rtl/heapfixed-debug.sasm create mode 100644 src/rtl/heapfixed.sasm create mode 100644 src/rtl/heaptest.sasm create mode 100644 src/rtl/heapvar.sasm create mode 100644 src/rtl/interp-rtlheap.sasm create mode 100644 src/rtl/makefile create mode 100644 src/rtl/mjrtl-spim.sasm create mode 100644 src/rtl/mjrtl.c create mode 100644 src/rtl/mjrtl.sasm create mode 100644 src/rtl/mm-param.sasm create mode 100644 src/rtl/nonexports.scm create mode 100644 src/rtl/r5rs-library.scm create mode 100644 src/rtl/r5rs-native.scm create mode 100644 src/rtl/r5rs-syntax.scm create mode 100644 src/rtl/r5rs-wrap.scm create mode 100644 src/rtl/rtlheap.sasm create mode 100644 src/rtl/rtlscheme.c create mode 100644 src/rtl/rtlscheme.sasm create mode 100644 src/rtl/sasm.h create mode 100644 src/rtl/scheme-main.sasm create mode 100644 src/rtl/scheme.java create mode 100644 src/rtl/scheme.javap create mode 100644 src/rtl/spim-main.s create mode 100644 src/run-ts.scm create mode 100644 src/sasm-interp-mips.scm create mode 100644 src/sasm-interp-ts.scm create mode 100644 src/sasm-interp-x86.scm create mode 100644 src/sasm-interp.scm create mode 100644 src/sasm-mips.scm create mode 100644 src/sasm-opt-mips.scm create mode 100644 src/sasm-opt-ts.scm create mode 100644 src/sasm-opt.dep create mode 100644 src/sasm-opt.scm create mode 100644 src/sasm-ts.scm create mode 100644 src/sasm-util.scm create mode 100644 src/sasm.dep create mode 100644 src/sasm.scm create mode 100644 src/sasm/fastgraph.scm create mode 100644 src/sasm/fastset.scm create mode 100644 src/sasm/fp.scm create mode 100644 src/sasm/machdesc.scm create mode 100644 src/sasm/nasmx86/arithmetic.scm create mode 100644 src/sasm/nasmx86/base.scm create mode 100644 src/sasm/nasmx86/binop.scm create mode 100644 src/sasm/nasmx86/bitwise-const.scm create mode 100644 src/sasm/nasmx86/call.scm create mode 100644 src/sasm/nasmx86/compare.scm create mode 100644 src/sasm/nasmx86/control.scm create mode 100644 src/sasm/nasmx86/data.scm create mode 100644 src/sasm/nasmx86/debug.scm create mode 100644 src/sasm/nasmx86/interp.scm create mode 100644 src/sasm/nasmx86/labels.scm create mode 100644 src/sasm/nasmx86/load-array.scm create mode 100644 src/sasm/nasmx86/machine.scm create mode 100644 src/sasm/nasmx86/mul.scm create mode 100644 src/sasm/nasmx86/preamble.scm create mode 100644 src/sasm/nasmx86/return.scm create mode 100644 src/sasm/nasmx86/shift.scm create mode 100644 src/sasm/nasmx86/stack.scm create mode 100644 src/sasm/nasmx86/store-array.scm create mode 100644 src/sasm/nasmx86/util.scm create mode 100644 src/sasm/parse/constant-operand.scm create mode 100644 src/sasm/parse/data-entry.scm create mode 100644 src/sasm/parse/extern.scm create mode 100644 src/sasm/parse/instruction.scm create mode 100644 src/sasm/parse/lvalue-operand.scm create mode 100644 src/sasm/parse/member.scm create mode 100644 src/sasm/parse/operand.scm create mode 100644 src/sasm/parse/operation.scm create mode 100644 src/sasm/parse/program.scm create mode 100644 src/sasm/parse/register-operand.scm create mode 100644 src/sasm/parse/statement.scm create mode 100644 src/sasm/parse/symconst-entry.scm create mode 100644 src/sasm/parse/syntax.scm create mode 100644 src/sasm/parse/util.scm create mode 100644 src/sasm/sasm-analyze.scm create mode 100644 src/sasm/sasm-ast.scm create mode 100644 src/sasm/sasm-codegen.scm create mode 100644 src/sasm/sasm-core.scm create mode 100644 src/sasm/sasm-dataflow.scm create mode 100644 src/sasm/sasm-eval.scm create mode 100644 src/sasm/sasm-insel.scm create mode 100644 src/sasm/sasm-insn.scm create mode 100644 src/sasm/sasm-interp-spec.scm create mode 100644 src/sasm/sasm-interp.scm create mode 100644 src/sasm/sasm-machine.scm create mode 100644 src/sasm/sasm-mips.scm create mode 100644 src/sasm/sasm-msil.scm create mode 100644 src/sasm/sasm-nasmx86.scm create mode 100644 src/sasm/sasm-opt.scm create mode 100644 src/sasm/sasm-parse.scm create mode 100644 src/sasm/sasm-regalloc.scm create mode 100644 src/sasm/sasm-rewrite.scm create mode 100644 src/sasm/sasm-tracing.scm create mode 100644 src/sasm/sasm-tx.scm create mode 100644 src/sasm/sasm-visitor.scm create mode 100644 src/sasm/sasm.scm create mode 100644 src/sasm/tx/assemble.scm create mode 100644 src/sasm/tx/config.scm create mode 100644 src/sasm/tx/context.scm create mode 100644 src/sasm/tx/emit.scm create mode 100644 src/sasm/tx/globals.scm create mode 100644 src/sasm/tx/interp.scm create mode 100644 src/sasm/tx/labels.scm create mode 100644 src/sasm/tx/main.scm create mode 100644 src/sasm/tx/read.scm create mode 100644 src/sasm/tx/registers.scm create mode 100644 src/sasm/tx/regrule.scm create mode 100644 src/sasm/tx/rewrite.scm create mode 100644 src/sasm/tx/stmt.scm create mode 100644 src/sasm/tx/symconst.scm create mode 100644 src/sasm/tx/util.scm create mode 100644 src/scheme-compiler-ts.scm create mode 100644 src/scheme-compiler.dep create mode 100644 src/scheme-compiler.scm create mode 100644 src/scheme-gluec-ts.scm create mode 100644 src/scheme-gluec.scm create mode 100644 src/scheme-interpreter-ts.scm create mode 100644 src/scheme-interpreter.scm create mode 100644 src/scheme/base-syntax.scm create mode 100644 src/scheme/compiler/codegen.scm create mode 100644 src/scheme/compiler/codegen/application.scm create mode 100644 src/scheme/compiler/codegen/emit.scm create mode 100644 src/scheme/compiler/codegen/epilogue.scm create mode 100644 src/scheme/compiler/codegen/immediate.scm create mode 100644 src/scheme/compiler/codegen/lambda.scm create mode 100644 src/scheme/compiler/codegen/letrec.scm create mode 100644 src/scheme/compiler/codegen/pretty-print.scm create mode 100644 src/scheme/compiler/codegen/reference.scm create mode 100644 src/scheme/compiler/codegen/set.scm create mode 100644 src/scheme/compiler/codegen/tailcall.scm create mode 100644 src/scheme/compiler/codegen/targets.scm create mode 100644 src/scheme/compiler/context.scm create mode 100644 src/scheme/compiler/cps.scm create mode 100644 src/scheme/compiler/env.scm create mode 100644 src/scheme/compiler/gc.scm create mode 100644 src/scheme/compiler/labels.scm create mode 100644 src/scheme/compiler/linkage.scm create mode 100644 src/scheme/compiler/settings.scm create mode 100644 src/scheme/genproc.scm create mode 100644 src/scheme/meta-eval.scm create mode 100644 src/scheme/syntax/core.scm create mode 100644 src/scheme/syntax/core/context.scm create mode 100644 src/scheme/syntax/core/env.scm create mode 100644 src/scheme/syntax/core/expand.scm create mode 100644 src/scheme/syntax/core/macro.scm create mode 100644 src/scheme/syntax/core/reference.scm create mode 100644 src/scheme/syntax/core/specform.scm create mode 100644 src/scheme/syntax/expand-context.scm create mode 100644 src/scheme/syntax/expander.scm create mode 100644 src/scheme/syntax/specform.scm create mode 100644 src/scheme/syntax/syntax.scm create mode 100644 src/scheme/tag.scm create mode 100644 src/scheme/transforms/cps.scm create mode 100644 src/scheme/transforms/internal-defines.scm create mode 100644 src/scp/frontend/java/ast/ArrayTypeSpecifier.java create mode 100644 src/scp/frontend/java/ast/ClassBody.java create mode 100644 src/scp/frontend/java/ast/ClassList.java create mode 100644 src/scp/frontend/java/ast/ClassPart.java create mode 100644 src/scp/frontend/java/ast/ClassParts.java create mode 100644 src/scp/frontend/java/ast/FieldDefinition.java create mode 100644 src/scp/frontend/java/ast/MainClass.java create mode 100644 src/scp/frontend/java/ast/MethodAttributes.java create mode 100644 src/scp/frontend/java/ast/MethodBody.java create mode 100644 src/scp/frontend/java/ast/MethodDefinition.java create mode 100644 src/scp/frontend/java/ast/Node.java create mode 100644 src/scp/frontend/java/ast/Parameter.java create mode 100644 src/scp/frontend/java/ast/ParameterList.java create mode 100644 src/scp/frontend/java/ast/Program.java create mode 100644 src/scp/frontend/java/ast/SimpleTypeSpecifier.java create mode 100644 src/scp/frontend/java/ast/Statement.java create mode 100644 src/scp/frontend/java/ast/StatementBlock.java create mode 100644 src/scp/frontend/java/ast/StaticFieldDefinition.java create mode 100644 src/scp/frontend/java/ast/TypeSpecifier.java create mode 100644 src/scp/frontend/java/ast/VariableDefinition.java create mode 100644 src/scp/frontend/java/ast/VariableDefinitionBlock.java create mode 100644 src/scp/frontend/java/ast/Visitor.java create mode 100644 src/scp/frontend/java/ast/_Class.java create mode 100644 src/scp/frontend/java/lexer/AdjacencyRule.java create mode 100644 src/scp/frontend/java/lexer/JavaLexerData.java create mode 100644 src/scp/frontend/java/lexer/Lexer.java create mode 100644 src/scp/frontend/java/lexer/LexerTest.java create mode 100644 src/scp/frontend/java/lexer/Token.java create mode 100644 src/scp/frontend/java/lexer/TokenType.java create mode 100644 src/selfbld.win32.makefile create mode 100644 src/smake-grammar.scm create mode 100644 src/smake-lexer-test.scm create mode 100644 src/smake-lexer.scm create mode 100644 src/smake-parser.scm create mode 100644 src/smake-tokens.scm create mode 100644 src/smake.scm create mode 100644 src/spim-makefile create mode 100644 src/symtab.scm create mode 100644 src/tailcall.scm create mode 100644 src/tests.makefile create mode 100644 src/tests.win32.makefile create mode 100644 src/tests/Arrays.java create mode 100644 src/tests/BinarySearch.java create mode 100644 src/tests/BinaryTree.java create mode 100644 src/tests/Bitwise.java create mode 100644 src/tests/BubbleSort.java create mode 100644 src/tests/CharString.java create mode 100644 src/tests/Count.java create mode 100644 src/tests/CtorTest.java create mode 100644 src/tests/Factorial.java create mode 100644 src/tests/LinearSearch.java create mode 100644 src/tests/LinkedList.java create mode 100644 src/tests/Messy.java create mode 100644 src/tests/MyFactorial.java create mode 100644 src/tests/NumberToString.java create mode 100644 src/tests/ObjArray.java create mode 100644 src/tests/OpEquals.java create mode 100644 src/tests/OverrideTest.java create mode 100644 src/tests/QuickSort.java create mode 100644 src/tests/Rectangles.java create mode 100644 src/tests/StaticMembers.java create mode 100644 src/tests/StaticMethods.java create mode 100644 src/tests/SubExp.java create mode 100644 src/tests/TreeVisitor.java create mode 100644 src/tests/TwoArgs.java create mode 100644 src/tests/apply.scm create mode 100644 src/tests/argv.scm create mode 100644 src/tests/badapply.cmd create mode 100644 src/tests/badapply.scm create mode 100644 src/tests/badsrhi.cmd create mode 100644 src/tests/badsrhi.scm create mode 100644 src/tests/badsrlo.cmd create mode 100644 src/tests/badsrlo.scm create mode 100644 src/tests/badsshi.cmd create mode 100644 src/tests/badsshi.scm create mode 100644 src/tests/badsslo.cmd create mode 100644 src/tests/badsslo.scm create mode 100644 src/tests/badvrhi.cmd create mode 100644 src/tests/badvrhi.scm create mode 100644 src/tests/badvrlo.cmd create mode 100644 src/tests/badvrlo.scm create mode 100644 src/tests/badvshi.cmd create mode 100644 src/tests/badvshi.scm create mode 100644 src/tests/badvslo.cmd create mode 100644 src/tests/badvslo.scm create mode 100644 src/tests/baseline/Arrays.actual create mode 100644 src/tests/baseline/BinarySearch.actual create mode 100644 src/tests/baseline/BinaryTree.actual create mode 100644 src/tests/baseline/Bitwise.actual create mode 100644 src/tests/baseline/BubbleSort.actual create mode 100644 src/tests/baseline/CharString.actual create mode 100644 src/tests/baseline/Count.actual create mode 100644 src/tests/baseline/CtorTest.actual create mode 100644 src/tests/baseline/Factorial.actual create mode 100644 src/tests/baseline/GCStress-gc.actual create mode 100644 src/tests/baseline/GCStress2-gc.actual create mode 100644 src/tests/baseline/GCTest1-gc.actual create mode 100644 src/tests/baseline/LinearSearch.actual create mode 100644 src/tests/baseline/LinkedList.actual create mode 100644 src/tests/baseline/Messy.actual create mode 100644 src/tests/baseline/MyFactorial.actual create mode 100644 src/tests/baseline/NumberToString.actual create mode 100644 src/tests/baseline/ObjArray.actual create mode 100644 src/tests/baseline/OpEquals.actual create mode 100644 src/tests/baseline/OverrideTest.actual create mode 100644 src/tests/baseline/QuickSort.actual create mode 100644 src/tests/baseline/Rectangles.actual create mode 100644 src/tests/baseline/Speed-perf.actual create mode 100644 src/tests/baseline/Speed2-perf.actual create mode 100644 src/tests/baseline/StaticMembers.actual create mode 100644 src/tests/baseline/StaticMethods.actual create mode 100644 src/tests/baseline/SubExp.actual create mode 100644 src/tests/baseline/TreeVisitor.actual create mode 100644 src/tests/baseline/TwoArgs.actual create mode 100644 src/tests/baseline/apply-s.actual create mode 100644 src/tests/baseline/argv-s.actual create mode 100644 src/tests/baseline/badapply-s.actual create mode 100644 src/tests/baseline/badsrhi-s.actual create mode 100644 src/tests/baseline/badsrlo-s.actual create mode 100644 src/tests/baseline/badsshi-s.actual create mode 100644 src/tests/baseline/badsslo-s.actual create mode 100644 src/tests/baseline/badvrhi-s.actual create mode 100644 src/tests/baseline/badvrlo-s.actual create mode 100644 src/tests/baseline/badvshi-s.actual create mode 100644 src/tests/baseline/badvslo-s.actual create mode 100644 src/tests/baseline/call.sasm-interp.actual create mode 100644 src/tests/baseline/call.sasm-util.actual create mode 100644 src/tests/baseline/char-case-s.actual create mode 100644 src/tests/baseline/char-s.actual create mode 100644 src/tests/baseline/const-s.actual create mode 100644 src/tests/baseline/const2-s.actual create mode 100644 src/tests/baseline/count-s.actual create mode 100644 src/tests/baseline/delete-s.actual create mode 100644 src/tests/baseline/disp1-s.actual create mode 100644 src/tests/baseline/disp2-s.actual create mode 100644 src/tests/baseline/disptest-s.actual create mode 100644 src/tests/baseline/disptest2-s.actual create mode 100644 src/tests/baseline/eq-s.actual create mode 100644 src/tests/baseline/equal-s.actual create mode 100644 src/tests/baseline/eqv-s.actual create mode 100644 src/tests/baseline/factorial-s.actual create mode 100644 src/tests/baseline/factorial2-s.actual create mode 100644 src/tests/baseline/fastset-unittest.actual create mode 100644 src/tests/baseline/gc-test.sasm-interp.actual create mode 100644 src/tests/baseline/gc-test.sasm-util.actual create mode 100644 src/tests/baseline/genparse-unittest.actual create mode 100644 src/tests/baseline/genproc-unittest.actual create mode 100644 src/tests/baseline/getenv-s.actual create mode 100644 src/tests/baseline/hw-s.actual create mode 100644 src/tests/baseline/hw2-s.actual create mode 100644 src/tests/baseline/hw3-s.actual create mode 100644 src/tests/baseline/implambda-s.actual create mode 100644 src/tests/baseline/inputfile-s.actual create mode 100644 src/tests/baseline/lambda1-s.actual create mode 100644 src/tests/baseline/list-s.actual create mode 100644 src/tests/baseline/list-unittest.actual create mode 100644 src/tests/baseline/mjrtl-mips-test.sasm-interp.actual create mode 100644 src/tests/baseline/mjrtl-mips-test.sasm-util.actual create mode 100644 src/tests/baseline/mkstring-s.actual create mode 100644 src/tests/baseline/mkvec-s.actual create mode 100644 src/tests/baseline/modquot-s.actual create mode 100644 src/tests/baseline/mul-s.actual create mode 100644 src/tests/baseline/n2s-s.actual create mode 100644 src/tests/baseline/nest.sasm-interp.actual create mode 100644 src/tests/baseline/nest.sasm-util.actual create mode 100644 src/tests/baseline/num2str-s.actual create mode 100644 src/tests/baseline/opdiv-s.actual create mode 100644 src/tests/baseline/opeq-s.actual create mode 100644 src/tests/baseline/opgt-s.actual create mode 100644 src/tests/baseline/oplt-s.actual create mode 100644 src/tests/baseline/opminus-s.actual create mode 100644 src/tests/baseline/opmul-s.actual create mode 100644 src/tests/baseline/opplus-s.actual create mode 100644 src/tests/baseline/order-eval-s.actual create mode 100644 src/tests/baseline/outputfile-s.actual create mode 100644 src/tests/baseline/outputfile.dat create mode 100644 src/tests/baseline/pair-s.actual create mode 100644 src/tests/baseline/pat-unittest.actual create mode 100644 src/tests/baseline/peekchar-s.actual create mode 100644 src/tests/baseline/pred-s.actual create mode 100644 src/tests/baseline/r5rs1-s.actual create mode 100644 src/tests/baseline/r5rs2-s.actual create mode 100644 src/tests/baseline/r5rs3-s.actual create mode 100644 src/tests/baseline/read-s.actual create mode 100644 src/tests/baseline/read10-s.actual create mode 100644 src/tests/baseline/read11-s.actual create mode 100644 src/tests/baseline/read2-s.actual create mode 100644 src/tests/baseline/read3-s.actual create mode 100644 src/tests/baseline/read4-s.actual create mode 100644 src/tests/baseline/read5-s.actual create mode 100644 src/tests/baseline/read6-s.actual create mode 100644 src/tests/baseline/read7-s.actual create mode 100644 src/tests/baseline/read8-s.actual create mode 100644 src/tests/baseline/read9-s.actual create mode 100644 src/tests/baseline/regex-unittest.actual create mode 100644 src/tests/baseline/rename-s.actual create mode 100644 src/tests/baseline/sasm-insn-unittest.actual create mode 100644 src/tests/baseline/scm1-s.actual create mode 100644 src/tests/baseline/set1-s.actual create mode 100644 src/tests/baseline/stat-s.actual create mode 100644 src/tests/baseline/str2num-s.actual create mode 100644 src/tests/baseline/str2num2-s.actual create mode 100644 src/tests/baseline/string-s.actual create mode 100644 src/tests/baseline/string2-s.actual create mode 100644 src/tests/baseline/string3-s.actual create mode 100644 src/tests/baseline/stringset-s.actual create mode 100644 src/tests/baseline/strref-s.actual create mode 100644 src/tests/baseline/sum-s.actual create mode 100644 src/tests/baseline/sym1-s.actual create mode 100644 src/tests/baseline/temp.sasm-interp.actual create mode 100644 src/tests/baseline/temp.sasm-util.actual create mode 100644 src/tests/baseline/test-read-s.actual create mode 100644 src/tests/baseline/test-s.actual create mode 100644 src/tests/baseline/test1-cs.actual create mode 100644 src/tests/baseline/test2-cs.actual create mode 100644 src/tests/baseline/vararg-s.actual create mode 100644 src/tests/baseline/wc-s.actual create mode 100644 src/tests/baseline/write-s.actual create mode 100644 src/tests/call.sasm create mode 100644 src/tests/char-case.scm create mode 100644 src/tests/char.scm create mode 100644 src/tests/const.scm create mode 100644 src/tests/const2.scm create mode 100644 src/tests/count.scm create mode 100644 src/tests/cseconds.scm create mode 100644 src/tests/delete.scm create mode 100644 src/tests/disp1.scm create mode 100644 src/tests/disp2.scm create mode 100644 src/tests/disptest.scm create mode 100644 src/tests/disptest2.scm create mode 100644 src/tests/eq.scm create mode 100644 src/tests/equal.scm create mode 100644 src/tests/eqv.scm create mode 100644 src/tests/factorial.scm create mode 100644 src/tests/factorial2.scm create mode 100644 src/tests/fastset.ss create mode 100644 src/tests/gc-test.sasm create mode 100644 src/tests/gc/GCStress.java create mode 100644 src/tests/gc/GCStress2.java create mode 100644 src/tests/gc/GCStress3.java create mode 100644 src/tests/gc/GCTest1.java create mode 100644 src/tests/gc/GCTest2.java create mode 100644 src/tests/gc/GCTest3.java create mode 100644 src/tests/gc/GCTest4.java create mode 100644 src/tests/gc1.scm create mode 100644 src/tests/genparse.ss create mode 100644 src/tests/genproc.ss create mode 100644 src/tests/getenv.scm create mode 100644 src/tests/hw.scm create mode 100644 src/tests/hw2.scm create mode 100644 src/tests/hw3.scm create mode 100644 src/tests/if.scm create mode 100644 src/tests/implambda.scm create mode 100644 src/tests/inputfile.scm create mode 100644 src/tests/lambda1.scm create mode 100644 src/tests/letrec.scm create mode 100644 src/tests/list.scm create mode 100644 src/tests/list.ss create mode 100644 src/tests/mjrtl-mips-test.sasm create mode 100644 src/tests/mkstring.scm create mode 100644 src/tests/mkvec.scm create mode 100644 src/tests/modquot.scm create mode 100644 src/tests/mul.scm create mode 100644 src/tests/n2s.scm create mode 100644 src/tests/neg/GCTest2.java create mode 100644 src/tests/neg/Speed.java create mode 100644 src/tests/nest.sasm create mode 100644 src/tests/num2str.scm create mode 100644 src/tests/opdiv.scm create mode 100644 src/tests/opeq.scm create mode 100644 src/tests/opgt.scm create mode 100644 src/tests/oplt.scm create mode 100644 src/tests/opminus.scm create mode 100644 src/tests/opmul.scm create mode 100644 src/tests/opplus.scm create mode 100644 src/tests/order-eval.scm create mode 100644 src/tests/outputfile.scm create mode 100644 src/tests/pair.scm create mode 100644 src/tests/pat.ss create mode 100644 src/tests/peekchar.scm create mode 100644 src/tests/perf/Speed.java create mode 100644 src/tests/perf/Speed2.java create mode 100644 src/tests/pred.scm create mode 100644 src/tests/printer-helper.scm create mode 100644 src/tests/printer.scm create mode 100644 src/tests/quot.scm create mode 100644 src/tests/r5rs1.scm create mode 100644 src/tests/r5rs2.scm create mode 100644 src/tests/r5rs3.scm create mode 100644 src/tests/read-dat-imp.scm create mode 100644 src/tests/read-dat.scm create mode 100644 src/tests/read-dat2.scm create mode 100644 src/tests/read-dat3.scm create mode 100644 src/tests/read-dat4.scm create mode 100644 src/tests/read-escapes.scm create mode 100644 src/tests/read-ext-id.scm create mode 100644 src/tests/read-namedchar.scm create mode 100644 src/tests/read.scm create mode 100644 src/tests/read10.scm create mode 100644 src/tests/read11.scm create mode 100644 src/tests/read2.scm create mode 100644 src/tests/read3.scm create mode 100644 src/tests/read4.scm create mode 100644 src/tests/read5.scm create mode 100644 src/tests/read6.scm create mode 100644 src/tests/read7.scm create mode 100644 src/tests/read8.scm create mode 100644 src/tests/read9.scm create mode 100644 src/tests/regex.ss create mode 100644 src/tests/rename.scm create mode 100644 src/tests/sasm-insn.ss create mode 100644 src/tests/sasm1.scm create mode 100644 src/tests/scm1.scm create mode 100644 src/tests/set1.scm create mode 100644 src/tests/smake-test.txt create mode 100644 src/tests/stat-dat.scm create mode 100644 src/tests/stat.scm create mode 100644 src/tests/str2num.scm create mode 100644 src/tests/str2num2.scm create mode 100644 src/tests/string.scm create mode 100644 src/tests/string2.scm create mode 100644 src/tests/string3.scm create mode 100644 src/tests/stringset.scm create mode 100644 src/tests/strref.scm create mode 100644 src/tests/sum.scm create mode 100644 src/tests/sym1.scm create mode 100644 src/tests/syntax1.scm create mode 100644 src/tests/syntax1.syn create mode 100644 src/tests/syntax2.scm create mode 100644 src/tests/temp.sasm create mode 100644 src/tests/test-read.scm create mode 100644 src/tests/test.scm create mode 100644 src/tests/test1.cs create mode 100644 src/tests/test2.cs create mode 100644 src/tests/vararg.scm create mode 100644 src/tests/wc.scm create mode 100644 src/tests/write.scm create mode 100644 src/typechk.scm create mode 100644 src/types.scm create mode 100644 src/util/counting.scm create mode 100644 src/util/filesystem.scm create mode 100644 src/util/format.scm create mode 100644 src/util/io.scm create mode 100644 src/util/list.scm create mode 100644 src/util/matrix.scm create mode 100644 src/util/output-file.scm create mode 100644 src/util/readhelp.scm create mode 100644 src/util/rfilact.scm create mode 100644 src/util/string.scm create mode 100644 src/util/symbol.scm create mode 100644 src/util/vector.scm diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5976907 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 rtrusso + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bbb6076 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Quick Start + +## Windows + +- Ensure GCC, GNU make, NASM, diff in path +- run src\go.cmd + +## Linux + +*work in progress* + +# Sunnyvale Compiler Platform + +This codebase aspires to facilitate the rapid or experimental +development of traditional ("ahead-of-time") compilers for a wide +range of programming languages. + +The codebase consists of these major components: + +- Frontends for a subset of the Scheme and Java programming languages +- Lexer and parser generator tools +- an intermediate language: Symbolic Assembly or SASM +- A backend with code analysis and improvement phases (optimizer) +- Translation of SASM to practical assembly languages (x86, MIPS) +- A runtime library with basic memory management and a garbage collector + +The idea is that to build a compiler for some programming language, +one has to mainly write just a frontend that emits SASM, and runtime +library, and take advantage of as many of the existing components as +possible to get that working as quickly and/or easily as +possible. Ideally, there should also be reuse of the runtime +components to the extent possible. + +In this way it has similar goals to something like .NET or the JVM +without all that mucking about in virtual machines. + +- [Status](readme/Status.md) +- [Dependencies](readme/Depend.md) +- [SASM Introduction](readme/SASM.md) +- [Tools](readme/Tools.md) diff --git a/bootstrap/.gitignore b/bootstrap/.gitignore new file mode 100644 index 0000000..47fada0 --- /dev/null +++ b/bootstrap/.gitignore @@ -0,0 +1,7 @@ +tinyscheme-1.41/dynload.o +tinyscheme-1.41/scheme +tinyscheme-1.41/scheme.o +tinyscheme-1.41/libtinyscheme.a +tinyscheme-1.41/libtinyscheme.so +tinyscheme-1.41/scheme.exe +tinyscheme-1.41/libtinyscheme.dll diff --git a/bootstrap/bootstrap-ops-5.c b/bootstrap/bootstrap-ops-5.c new file mode 100644 index 0000000..42c5ffa --- /dev/null +++ b/bootstrap/bootstrap-ops-5.c @@ -0,0 +1,81 @@ + + /* ========== other i/o part ========== */ + case OP_GETENV: { + char *env = getenv(strvalue(car(sc->args))); + if (env) { + x=mk_string(sc,env); + s_return(sc,x); + } else { + s_retbool(0); + } + } + + case OP_SETENV: { + char *name = strvalue(car(sc->args)); + char *val = strvalue(cadr(sc->args)); +#ifdef TS_BOOTSTRAP_MINGW32 + BOOL b = SetEnvironmentVariableA(name, val); + s_retbool(b); +#else + int s = (0==setenv(name,val,1)); + s_retbool(s); +#endif + } + + case OP_UNLINK: { + int s = (0==unlink(strvalue(car(sc->args)))); + s_retbool(s); + } + + case OP_MKDIR: { +#ifdef TS_BOOTSTRAP_MINGW32 + int s = (0==mkdir(strvalue(car(sc->args)))); +#else + int s = (0==mkdir(strvalue(car(sc->args)), 0777)); +#endif + s_retbool(s); + } + + case OP_ELAPSED_S: { + static time_t t_base = 0; + time_t t_now; + if (t_base == 0) { time(&t_base); } + time(&t_now); + s_return(sc,mk_integer(sc,(t_now - t_base))); + } + + case OP_ELAPSED_MS: { + static struct timeval tv_base = {0,0}; + struct timeval tv_now; + int ms; + if (tv_base.tv_sec==0) { gettimeofday(&tv_base, NULL); } + gettimeofday(&tv_now, NULL); + ms = (tv_now.tv_sec - tv_base.tv_sec) * 1000; + ms += (tv_now.tv_usec - tv_base.tv_usec) / 1000; + s_return(sc,mk_integer(sc,ms)); + } + + case OP_STAT: { + struct stat buf; + int s = (0==stat(strvalue(car(sc->args)),&buf)); + if (s) { + pointer vec; + vec = mk_vector(sc,10); + set_vector_elem(vec,7,mk_integer(sc,buf.st_size)); + set_vector_elem(vec,9,mk_integer(sc,buf.st_mtime)); + s_return(sc,vec); + } else { + s_retbool(0); + } + } + + case OP_RENAME_FILE: { + char *old = strvalue(car(sc->args)); + char *new = strvalue(cadr(sc->args)); + int s = (0==rename(old,new)); + s_retbool(s); + } + + case OP_EVALCTR: { + s_return(sc,mk_integer(sc,Eval_Cycle_Count)); + } diff --git a/bootstrap/bootstrap-ops-5.h b/bootstrap/bootstrap-ops-5.h new file mode 100644 index 0000000..6e6a8b9 --- /dev/null +++ b/bootstrap/bootstrap-ops-5.h @@ -0,0 +1,9 @@ + _OP_DEF(opexe_5, "getenv", 1, 1, TST_STRING, OP_GETENV ) + _OP_DEF(opexe_5, "setenv", 2, 2, TST_STRING TST_STRING, OP_SETENV ) + _OP_DEF(opexe_5, "delete-file", 1, 1, TST_STRING, OP_UNLINK ) + _OP_DEF(opexe_5, "create-directory", 1, 1, TST_STRING, OP_MKDIR ) + _OP_DEF(opexe_5, "current-seconds", 0, 0, 0, OP_ELAPSED_S ) + _OP_DEF(opexe_5, "current-milliseconds", 0, 0, 0, OP_ELAPSED_MS ) + _OP_DEF(opexe_5, "stat", 1, 1, TST_STRING, OP_STAT ) + _OP_DEF(opexe_5, "rename-file", 2, 2, TST_STRING TST_STRING, OP_RENAME_FILE ) + _OP_DEF(opexe_5, "current-evaluation-counter", 0, 0, 0, OP_EVALCTR ) diff --git a/bootstrap/bootstrap.h b/bootstrap/bootstrap.h new file mode 100644 index 0000000..dbf7934 --- /dev/null +++ b/bootstrap/bootstrap.h @@ -0,0 +1,5 @@ +#ifdef TS_BOOTSTRAP_MINGW32 +#include +#include +#include +#endif diff --git a/bootstrap/tinyscheme-1.41/BUILDING b/bootstrap/tinyscheme-1.41/BUILDING new file mode 100644 index 0000000..887598b --- /dev/null +++ b/bootstrap/tinyscheme-1.41/BUILDING @@ -0,0 +1,139 @@ + Building TinyScheme + ------------------- + +The included makefile includes logic for Linux, Solaris and Win32, and can +readily serve as an example for other OSes, especially Unixes. There are +a lot of compile-time flags in TinyScheme (preprocessor defines) that can trim +unwanted features. See next section. 'make all' and 'make clean' function as +expected. + +Autoconfing TinyScheme was once proposed, but the distribution would not be +so small anymore. There are few platform dependencies in TinyScheme, and in +general compiles out of the box. + + Customizing + ----------- + + The following symbols are defined to default values in scheme.h. + Use the -D flag of cc to set to either 1 or 0. + + STANDALONE + Define this to produce a standalone interpreter. + + USE_MATH + Includes math routines. + + USE_CHAR_CLASSIFIERS + Includes character classifier procedures. + + USE_ASCII_NAMES + Enable extended character notation based on ASCII names. + + USE_STRING_PORTS + Enables string ports. + + USE_ERROR_HOOK + To force system errors through user-defined error handling. + (see "Error handling") + + USE_TRACING + To enable use of TRACING. + + USE_COLON_HOOK + Enable use of qualified identifiers. (see "Colon Qualifiers - Packages") + Defining this as 0 has the rather drastic consequence that any code using + packages will stop working, and will have to be modified. It should only + be used if you *absolutely* need to use '::' in identifiers. + + USE_STRCASECMP + Defines stricmp as strcasecmp, for Unix. + + STDIO_ADDS_CR + Informs TinyScheme that stdio translates "\n" to "\r\n". For DOS/Windows. + + USE_DL + Enables dynamically loaded routines. If you define this symbol, you + should also include dynload.c in your compile. + + USE_PLIST + Enables property lists (not Standard Scheme stuff). Off by default. + + USE_NO_FEATURES + Shortcut to disable USE_MATH, USE_CHAR_CLASSIFIERS, USE_ASCII_NAMES, + USE_STRING_PORTS, USE_ERROR_HOOK, USE_TRACING, USE_COLON_HOOK, + USE_DL. + + USE_SCHEME_STACK + Enables 'cons' stack (the alternative is a faster calling scheme, which + breaks continuations). Undefine it if you don't care about strict compatibility + but you do care about faster execution. + + + OS-X tip + -------- + I don't have access to OS-X, but Brian Maher submitted the following tip: + +[1] Download and install fink (I installed fink in +/usr/local/fink) +[2] Install the 'dlcompat' package using fink as such: +> fink install dlcompat +[3] Make the following changes to the +tinyscheme-1.32.tar.gz + +diff -r tinyscheme-1.32/dynload.c +tinyscheme-1.32-new/dynload.c +24c24 +< #define SUN_DL +--- +> +Only in tinyscheme-1.32-new/: dynload.o +Only in tinyscheme-1.32-new/: libtinyscheme.a Only in tinyscheme-1.32-new/: libtinyscheme.so diff -r tinyscheme-1.32/makefile tinyscheme-1.32-new/makefile +33,34c33,43 +< LD = gcc +< LDFLAGS = -shared +--- +> #LD = gcc +> #LDFLAGS = -shared +> #DEBUG=-g -Wno-char-subscripts -O +> #SYS_LIBS= -ldl +> #PLATFORM_FEATURES= -DSUN_DL=1 +> +> # Mac OS X +> CC = gcc +> CFLAGS = -I/usr/local/fink/include +> LD = gcc +> LDFLAGS = -L/usr/local/fink/lib +37c46 +< PLATFORM_FEATURES= -DSUN_DL=1 +--- +> PLATFORM_FEATURES= -DSUN_DL=1 -DOSX +60c69 +< $(CC) -I. -c $(DEBUG) $(FEATURES) +$(DL_FLAGS) $< +--- +> $(CC) $(CFLAGS) -I. -c $(DEBUG) +$(FEATURES) $(DL_FLAGS) $< +66c75 +< $(CC) -o $@ $(DEBUG) $(OBJS) $(SYS_LIBS) +--- +> $(CC) $(LDFLAGS) -o $@ $(DEBUG) $(OBJS) +$(SYS_LIBS) +Only in tinyscheme-1.32-new/: scheme +diff -r tinyscheme-1.32/scheme.c +tinyscheme-1.32-new/scheme.c +60,61c60,61 +< #ifndef macintosh +< # include +--- +> #ifdef OSX +> /* Do nothing */ +62a63,65 +> # ifndef macintosh +> # include +> # else +77c80,81 +< #endif /* macintosh */ +--- +> # endif /* macintosh */ +> #endif /* !OSX */ +Only in tinyscheme-1.32-new/: scheme.o diff --git a/bootstrap/tinyscheme-1.41/CHANGES b/bootstrap/tinyscheme-1.41/CHANGES new file mode 100644 index 0000000..a8177c9 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/CHANGES @@ -0,0 +1,326 @@ +Change Log +---------- + +Version 1.41 + Bugs fixed: + #3020389 - Added makefile section for Mac OS X (SL) + #3286135 - Fixed num_mod routine which caused errors in use of modulo + #3290232 - Corrected version number shown on startup (GM) + #3394882 - Added missing #if in opdefines.h around get and put (DC) + #3395547 - Fix for the modulo procedure (DC) + #3400290 - Optimized append to make it an O(n) operation (DC) + #3493926 - Corrected flag used when building shared files on OSX (J) + + R5RS related changes: + #2866196 - Parser does not handle delimiters correctly + #3395548 - Add a decimal point to inexact numbers in atom2str (DC) + #3399331 - Make min/max return inexact when any argument is inexact + #3399332 - Compatability fix for expt. + #3399335 - Optional radix for string->number and number->string (DC) + #3400202 - Append with one argument should not return a list (DC) + #3400284 - Compatability fix for integer? + + Other changes: + - Added flags to makefile for MinGW/MSYS (TC) + - Moved variable declarations to avoid warnings with some compilers + - Don't print space after initial #( when printing vectors. + - Minor optimization for is_nonneg(). + - No need to round integers in OP_ROUND (#3400284) + - Fixes to code that reports line number with error (RC) + + Contributors: + Kevin Cozens, Gordon McNutt, Doug Currie, Sean Long, Tim Cas, Joey, + Richard Copley, and CMarinier. + +Version 1.40 + Bugs fixed: + #1964950 - Stop core dumps due to bad syntax in LET (and variants) + #2826594 - allow reverse to work on empty list (Tony Garnock-Jones) + Potential problem of arglist to foreign calls being wrongly GC'ed. + Fixed bug that read could loop forever (tehom). + + API changes: + Exposed is_list and list_length. + Added scheme_register_foreign_func_list and declarations for it (tehom) + Defined *compile-hook* (tehom) + + Other changes: + Updated is_list and list_length to handle circular lists. + Nested calling thru C has been made now safer (tehom) + Peter Michaux cleaned up port_rep_from_file + Added unwind-protect (tehom) + Some cleanups to in/outport and Eval_Cycle by Peter Michaux + Report error line number (Mostly by Sanel Zukan, back-compatibility by Tehom) + + Contributors: + Kevin Cozens, Dimitrios Souflis, Tom Breton, Peter Michaux, Sanel Zukan, + and Tony Garnock-Jones. + +Version 1.39 + Bugs fixed: + Fix for the load bug + Fixed parsing of octal coded characters. Fixes bug #1818018. + Added tests for when mk_vector is out of memory. Can't rely on sc->sink. + Fix for bug #1794369 + Finished feature-request 1599947: scheme_apply0 etc return values. + Partly provided feature-request 1599947: Expose list_length, eqv, etc + Provided feature-request 1599945, Scheme->C->Scheme calling. + Fix for bug 1593861 (behavior of is_integer) + Fix for bug 1589711 + Error checking of binding spec syntax in LET and LETREC. The bad syntax + was causing a segmentation fault in Linux. Complete fixes for bug #1817986. + Error checking of binding spec syntax in LET* + Bad syntax was causing core dump in Linux. + Fix for nasty gc bug + + R5RS changes: + R5RS requires numbers to be of equal value AND of the same type (ie. both + exact or inexact) in order to return #t from eqv?. R5RS compliance fix. + String output ports now conform to SRFI-6 + + Other changes: + Drew Yao fixed buffer overflow problems in mk_sharp_const. + put OP_T0LVL in charge of reacting to EOF + file_push checks array bounds (patch from Ray Lehtiniemi) + Changed to always use snprintf (Patch due to Ramiro bsd1628) + Updated usage information using text from the Manual.txt file. + +Version 1.38 + Interim release until the rewrite, mostly incorporating modifications + from Kevin Cozens. Small addition for Cygwin in the makefile, and + modifications by Andrew Guenther for Apple platforms. + +Version 1.37 + Joe Buehler submitted reserve_cells. + +Version 1.36 + Joe Buehler fixed a patch in the allocator. + Alexander Shendi moved the comment handling in the scanner, which + fixed an obscure bug for which Mike E had provided a patch as well. + Kevin Cozens has submitted some fixes and modifications which have + not been incorporated yet in their entirety. + +Version 1.35 + Todd Showalter discovered that the number of free cells reported + after GC was incorrect, which could also cause unnecessary allocations. + +Version 1.34 + Long missing version. Lots of bugfixes have accumulated in my email, so + I had to start using them. In this version, Keenan Pepper has submitted + a bugfix for the string comparison library procedure, Wouter Boeke + modified some code that was casting to the wrong type and crashed on + some machines, "SheppardCo" submitted a replacement "modulo" code and + Scott Fenton submitted lots of corrections that shut up some compiler + warnings. Brian Maher submitted instructions on how to build on OS-X. + I have to dig deeper into my mailbox and find earlier emails, too. + +Version 1.33 + Charles Hayden fixed a nasty GC bug of the new stack frame, while in + the process of porting TinyScheme to C++. He also submitted other + changes, and other people also had comments or requests, but the GC + bug was so important that this version is put through the door to + correct it. + +Version 1.32 + Stephen Gildea put some quality time on TinyScheme again, and made + a whole lot of changes to the interpreter that made it noticeably + faster. + +Version 1.31 + Patches to the hastily-done version 1.30. Stephen Gildea fixed + some things done wrongly, and Richard Russo fixed the makefile + for building on Windows. Property lists (heritage from MiniScheme) + are now optional and have dissappeared from the interface. They + should be considered as deprecated. + +Version 1.30 + After many months, I followed Preston Bannister's advice of + using macros and a single source text to keep the enums and the + dispatch table in sync, and I used his contributed "opdefines.h". + Timothy Downs contributed a helpful function, "scheme_call". + Stephen Gildea contributed new versions of the makefile and + practically all other sources. He created a built-in STRING-APPEND, + and fixed a lot of other bugs. + Ruhi Bloodworth reported fixes necessary for OS X and a small + bug in dynload.c. + +Version 1.29 + The previous version contained a lot of corrections, but there + were a lot more that still wait on a sheet of paper lost in a + carton someplace after my house move... Manuel Heras-Gilsanz + noticed this and resent his own contribution, which relies on + another bugfix that v.1.28 was missing: a problem with string + output, that this version fixes. I hope other people will take + the time to resend their contributions, if they didn't make it + to v.1.28. + +Version 1.28 + Many people have contacted me with bugfixes or remarks in + the three months I was inactive. A lot of them spotted that + scheme_deinit crashed while reporting gc results. They suggested + that sc->outport be set to NIL in scheme_deinit, which I did. + Dennis Taylor remarked that OP_VALUEPRINT reset sc->value instead + of preserving it. He submitted a modification which I adopted + partially. David Hovemeyer sent me many little changes, that you + will find in version 1.28, and Partice Stoessel modified the + float reader to conform to R5RS. + +Version 1.27 + Version 1.27 is the successor of 1.25. Bug fixes only, but I had to + release them so that everybody can profit. 'Backchar' tried to write + back to the string, which obviously didn't work for const strings. + 'Substring' didn't check for crossed start and end indices. Defines + changed to restore the ability to compile under MSVC. + +Version 1.26 + Version 1.26 was never released. I changed a lot of things, in fact + too much, even the garbage collector, and hell broke loose. I'll + try a more gradual approach next time. + +Version 1.25 + Types have been homogenized to be able to accommodate a different + representation. Plus, promises are no longer closures. Unfortunately, + I discovered that continuations and force/delay do not pass the SCM + test (and never did)... However, on the bright side, what little + modifications I did had a large impact on the footprint: + USE_NO_FEATURES now produces an object file of 63960 bytes on Linux! + +Version 1.24 + SCM tests now pass again after change in atom2str. + +Version 1.23 + Finally I managed to mess it up with my version control. Version + 1.22 actually lacked some of the things I have been fixing in the + meantime. This should be considered as a complete replacement for + 1.22. + +Version 1.22 + The new ports had a bug in LOAD. MK_CLOSURE is introduced. + Shawn Wagner inquired about string->number and number->string. + I added string->atom and atom->string and defined the number + functions from them. Doing that, I fixed WRITE applied to symbols + (it didn't quote them). Unfortunately, minimum build is now + slightly larger than 64k... I postpone action because Jason's idea + might solve it elegantly. + +Version 1.21 + Jason Felice submitted a radically different datatype representation + which he had implemented. While discussing its pros and cons, it + became apparent that the current implementation of ports suffered + from a grave fault: ports were not garbage-collected. I changed the + ports to be heap-allocated, which enabled the use of string ports + for loading. Jason also fixed errors in the garbage collection of + vectors. USE_VERBATIM is gone. "ssp_compiler.c" has a better solution + on HTML generation. A bug involving backslash notation in strings + has been fixed. '-c' flag now executes next argument as a stream of + Scheme commands. Foreign functions are now also heap allocated, + and scheme_define is used to define everything. + +Version 1.20 + Tracing has been added. The toplevel loop has been slightly + rearranged. Backquote reading for vector templates has been + sanitized. Symbol interning is now correct. Arithmetic functions + have been corrected. APPLY, MAP, FOR-EACH, numeric comparison + functions fixed. String reader/writer understands \xAA notation. + +Version 1.19 + Carriage Return now delimits identifiers. DOS-formatted Scheme files + can be used by Unix. Random number generator added to library. + Fixed some glitches of the new type-checking scheme. Fixed erroneous + (append '() 'a) behavior. Will continue with r4rstest.scm to + fix errors. + +Version 1.18 + The FFI has been extended. USE_VERBOSE_GC has gone. Anyone wanting + the same functionality can put (gcverbose #t) in init.scm. + print-width was removed, along with three corresponding op-codes. + Extended character constants with ASCII names were added. + mk_counted_string paves the way for full support of binary strings. + As much as possible of the type-checking chores were delegated + to the inner loop, thus reducing the code size to less than 4200 loc! + +Version 1.17 + Dynamically-loaded extensions are more fully integrated. + TinyScheme is now distributed under the BSD open-source license. + +Version 1.16 + Dynamically-loaded extensions introduced (USE_DL). + Santeri Paavolainen found a race condition: When a cons is executed, + and each of the two arguments is a constructing function, GC could + happen before all arguments are evaluated and cons() is called, and + the evaluated arguments would all be reclaimed! + Fortunately, such a case was rare in the code, although it is + a pitfall in new code and code in foreign functions. Currently, only + one such case remains, when COLON_HOOK is defined. + +Version 1.15 + David Gould also contributed some changes that speed up operation. + Kirk Zurell fixed HASPROP. + The Garbage Collection didn't collect all the garbage...fixed. + +Version 1.14 + Unfortunately, after Andre fixed the GC it became obvious that the + algorithm was too slow... Fortunately, David Gould found a way to + speed it up. + +Version 1.13 + Silly bug involving division by zero resolved by Roland Kaufman. + Macintoch support from Shmulik Regev. + Float parser bug fixed by Alexander Shendi. + GC bug from Andru Luvisi. + +Version 1.12 + Cis* incorrectly called isalpha() instead of isascii() + Added USE_CHAR_CLASSIFIERS, USE_STRING_PORTS. + +Version 1.11 + BSDI defines isnumber... changed all similar functions to is_* + EXPT now has correct definition. Added FLOOR,CEILING,TRUNCATE + and ROUND, courtesy of Bengt Kleberg. Preprocessor symbols now + have values 1 or 0, and can be set as compiler defines (proposed + by Andy Ganor *months* ago). 'prompt' and 'InitFile' can now be + defined during compilation, too. + +Version 1.10 + Another bug when file ends with comment! + Added DEFINE-MACRO in init.scm, courtesy of Andy Gaynor. + +Version 1.09 + Removed bug when READ met EOF. lcm. + +Version 1.08 + quotient,remainder and modulo. gcd. + +Version 1.07 + '=>' in cond now exists + list? now checks for circularity + some reader bugs removed + Reader is more consistent wrt vectors + Quote and Quasiquote work with vectors + +Version 1.06 + #! is now skipped + generic-assoc bug removed + strings are now managed differently, hack.txt is removed + various delicate points fixed + +Version 1.05 + Support for scripts, *args*, "-1" option. + Various R5RS procedures. + *sharp-hook* + Handles unmatched parentheses. + New architecture for procedures. + +Version 1.04 + Added missing T_ATOM bits... + Added vectors + Free-list is sorted by address, since vectors need consecutive cells. + (quit ) for use with scripts + +Version 1.03 (26 Aug 1998): + Extended .h with useful functions for FFI + Library: with-input-* etc. + Finished R5RS I/O, added string ports. + +Version 1.02 (25 Aug 1998): + First part of R5RS I/O. diff --git a/bootstrap/tinyscheme-1.41/COPYING b/bootstrap/tinyscheme-1.41/COPYING new file mode 100644 index 0000000..fb42141 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/COPYING @@ -0,0 +1,31 @@ + LICENSE TERMS + +Copyright (c) 2000, Dimitrios Souflis +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Dimitrios Souflis nor the names of the +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bootstrap/tinyscheme-1.41/Manual.txt b/bootstrap/tinyscheme-1.41/Manual.txt new file mode 100644 index 0000000..01253fe --- /dev/null +++ b/bootstrap/tinyscheme-1.41/Manual.txt @@ -0,0 +1,452 @@ + + + TinySCHEME Version 1.41 + + "Safe if used as prescribed" + -- Philip K. Dick, "Ubik" + +This software is open source, covered by a BSD-style license. +Please read accompanying file COPYING. +------------------------------------------------------------------------------- + + This Scheme interpreter is based on MiniSCHEME version 0.85k4 + (see miniscm.tar.gz in the Scheme Repository) + Original credits in file MiniSCHEMETribute.txt. + + D. Souflis (dsouflis@acm.org) + +------------------------------------------------------------------------------- + What is TinyScheme? + ------------------- + + TinyScheme is a lightweight Scheme interpreter that implements as large + a subset of R5RS as was possible without getting very large and + complicated. It is meant to be used as an embedded scripting interpreter + for other programs. As such, it does not offer IDEs or extensive toolkits + although it does sport a small top-level loop, included conditionally. + A lot of functionality in TinyScheme is included conditionally, to allow + developers freedom in balancing features and footprint. + + As an embedded interpreter, it allows multiple interpreter states to + coexist in the same program, without any interference between them. + Programmatically, foreign functions in C can be added and values + can be defined in the Scheme environment. Being a quite small program, + it is easy to comprehend, get to grips with, and use. + + Known bugs + ---------- + + TinyScheme is known to misbehave when memory is exhausted. + + + Things that keep missing, or that need fixing + --------------------------------------------- + + There are no hygienic macros. No rational or + complex numbers. No unwind-protect and call-with-values. + + Maybe (a subset of) SLIB will work with TinySCHEME... + + Decent debugging facilities are missing. Only tracing is supported + natively. + + + Scheme Reference + ---------------- + + If something seems to be missing, please refer to the code and + "init.scm", since some are library functions. Refer to the MiniSCHEME + readme as a last resort. + + Environments + (interaction-environment) + See R5RS. In TinySCHEME, immutable list of association lists. + + (current-environment) + The environment in effect at the time of the call. An example of its + use and its utility can be found in the sample code that implements + packages in "init.scm": + + (macro (package form) + `(apply (lambda () + ,@(cdr form) + (current-environment)))) + + The environment containing the (local) definitions inside the closure + is returned as an immutable value. + + (defined? ) (defined? ) + Checks whether the given symbol is defined in the current (or given) + environment. + + Symbols + (gensym) + Returns a new interned symbol each time. Will probably move to the + library when string->symbol is implemented. + + Directives + (gc) + Performs garbage collection immediatelly. + + (gcverbose) (gcverbose ) + The argument (defaulting to #t) controls whether GC produces + visible outcome. + + (quit) (quit ) + Stops the interpreter and sets the 'retcode' internal field (defaults + to 0). When standalone, 'retcode' is returned as exit code to the OS. + + (tracing ) + 1, turns on tracing. 0 turns it off. (Only when USE_TRACING is 1). + + Mathematical functions + Since rationals and complexes are absent, the respective functions + are also missing. + Supported: exp, log, sin, cos, tan, asin, acos, atan, floor, ceiling, + trunc, round and also sqrt and expt when USE_MATH=1. + Number-theoretical quotient, remainder and modulo, gcd, lcm. + Library: exact?, inexact?, odd?, even?, zero?, positive?, negative?, + exact->inexact. inexact->exact is a core function. + + Type predicates + boolean?,eof-object?,symbol?,number?,string?,integer?,real?,list?,null?, + char?,port?,input-port?,output-port?,procedure?,pair?,environment?', + vector?. Also closure?, macro?. + + Types + Types supported: + + Numbers (integers and reals) + Symbols + Pairs + Strings + Characters + Ports + Eof object + Environments + Vectors + + Literals + String literals can contain escaped quotes \" as usual, but also + \n, \r, \t, \xDD (hex representations) and \DDD (octal representations). + Note also that it is possible to include literal newlines in string + literals, e.g. + + (define s "String with newline here + and here + that can function like a HERE-string") + + Character literals contain #\space and #\newline and are supplemented + with #\return and #\tab, with obvious meanings. Hex character + representations are allowed (e.g. #\x20 is #\space). + When USE_ASCII_NAMES is defined, various control characters can be + referred to by their ASCII name. + 0 #\nul 17 #\dc1 + 1 #\soh 18 #\dc2 + 2 #\stx 19 #\dc3 + 3 #\etx 20 #\dc4 + 4 #\eot 21 #\nak + 5 #\enq 22 #\syn + 6 #\ack 23 #\etv + 7 #\bel 24 #\can + 8 #\bs 25 #\em + 9 #\ht 26 #\sub + 10 #\lf 27 #\esc + 11 #\vt 28 #\fs + 12 #\ff 29 #\gs + 13 #\cr 30 #\rs + 14 #\so 31 #\us + 15 #\si + 16 #\dle 127 #\del + + Numeric literals support #x #o #b and #d. Flonums are currently read only + in decimal notation. Full grammar will be supported soon. + + Quote, quasiquote etc. + As usual. + + Immutable values + Immutable pairs cannot be modified by set-car! and set-cdr!. + Immutable strings cannot be modified via string-set! + + I/O + As per R5RS, plus String Ports (see below). + current-input-port, current-output-port, + close-input-port, close-output-port, input-port?, output-port?, + open-input-file, open-output-file. + read, write, display, newline, write-char, read-char, peek-char. + char-ready? returns #t only for string ports, because there is no + portable way in stdio to determine if a character is available. + Also open-input-output-file, set-input-port, set-output-port (not R5RS) + Library: call-with-input-file, call-with-output-file, + with-input-from-file, with-output-from-file and + with-input-output-from-to-files, close-port and input-output-port? + (not R5RS). + String Ports: open-input-string, open-output-string, get-output-string, + open-input-output-string. Strings can be used with I/O routines. + + Vectors + make-vector, vector, vector-length, vector-ref, vector-set!, list->vector, + vector-fill!, vector->list, vector-equal? (auxiliary function, not R5RS) + + Strings + string, make-string, list->string, string-length, string-ref, string-set!, + substring, string->list, string-fill!, string-append, string-copy. + string=?, string?, string>?, string<=?, string>=?. + (No string-ci*? yet). string->number, number->string. Also atom->string, + string->atom (not R5RS). + + Symbols + symbol->string, string->symbol + + Characters + integer->char, char->integer. + char=?, char?, char<=?, char>=?. + (No char-ci*?) + + Pairs & Lists + cons, car, cdr, list, length, map, for-each, foldr, list-tail, + list-ref, last-pair, reverse, append. + Also member, memq, memv, based on generic-member, assoc, assq, assv + based on generic-assoc. + + Streams + head, tail, cons-stream + + Control features + Apart from procedure?, also macro? and closure? + map, for-each, force, delay, call-with-current-continuation (or call/cc), + eval, apply. 'Forcing' a value that is not a promise produces the value. + There is no call-with-values, values, nor dynamic-wind. Dynamic-wind in + the presence of continuations would require support from the abstract + machine itself. + + Property lists + TinyScheme inherited from MiniScheme property lists for symbols. + put, get. + + Dynamically-loaded extensions + (load-extension ) + Loads a DLL declaring foreign procedures. On Unix/Linux, one can make use + of the ld.so.conf file or the LD_RUN_PATH system variable in order to place + the library in a directory other than the current one. Please refer to the + appropriate 'man' page. + + Esoteric procedures + (oblist) + Returns the oblist, an immutable list of all the symbols. + + (macro-expand
) + Returns the expanded form of the macro call denoted by the argument + + (define-with-return ( ...) ) + Like plain 'define', but makes the continuation available as 'return' + inside the procedure. Handy for imperative programs. + + (new-segment ) + Allocates more memory segments. + + defined? + See "Environments" + + (get-closure-code ) + Gets the code as scheme data. + + (make-closure ) + Makes a new closure in the given environment. + + Obsolete procedures + (print-width ) + + Programmer's Reference + ---------------------- + + The interpreter state is initialized with "scheme_init". + Custom memory allocation routines can be installed with an alternate + initialization function: "scheme_init_custom_alloc". + Files can be loaded with "scheme_load_file". Strings containing Scheme + code can be loaded with "scheme_load_string". It is a good idea to + "scheme_load" init.scm before anything else. + + External data for keeping external state (of use to foreign functions) + can be installed with "scheme_set_external_data". + Foreign functions are installed with "assign_foreign". Additional + definitions can be added to the interpreter state, with "scheme_define" + (this is the way HTTP header data and HTML form data are passed to the + Scheme script in the Altera SQL Server). If you wish to define the + foreign function in a specific environment (to enhance modularity), + use "assign_foreign_env". + + The procedure "scheme_apply0" has been added with persistent scripts in + mind. Persistent scripts are loaded once, and every time they are needed + to produce HTTP output, appropriate data are passed through global + definitions and function "main" is called to do the job. One could + add easily "scheme_apply1" etc. + + The interpreter state should be deinitialized with "scheme_deinit". + + DLLs containing foreign functions should define a function named + init_. E.g. foo.dll should define init_foo, and bar.so + should define init_bar. This function should assign_foreign any foreign + function contained in the DLL. + + The first dynamically loaded extension available for TinyScheme is + a regular expression library. Although it's by no means an + established standard, this library is supposed to be installed in + a directory mirroring its name under the TinyScheme location. + + + Foreign Functions + ----------------- + + The user can add foreign functions in C. For example, a function + that squares its argument: + + pointer square(scheme *sc, pointer args) { + if(args!=sc->NIL) { + if(sc->isnumber(sc->pair_car(args))) { + double v=sc->rvalue(sc->pair_car(args)); + return sc->mk_real(sc,v*v); + } + } + return sc->NIL; + } + + Foreign functions are now defined as closures: + + sc->interface->scheme_define( + sc, + sc->global_env, + sc->interface->mk_symbol(sc,"square"), + sc->interface->mk_foreign_func(sc, square)); + + + Foreign functions can use the external data in the "scheme" struct + to implement any kind of external state. + + External data are set with the following function: + void scheme_set_external_data(scheme *sc, void *p); + + As of v.1.17, the canonical way for a foreign function in a DLL to + manipulate Scheme data is using the function pointers in sc->interface. + + Standalone + ---------- + + Usage: tinyscheme -? + or: tinyscheme [ ...] + followed by + -1 [ ...] + -c [ ...] + assuming that the executable is named tinyscheme. + + Use - in the place of a filename to denote stdin. + The -1 flag is meant for #! usage in shell scripts. If you specify + #! /somewhere/tinyscheme -1 + then tinyscheme will be called to process the file. For example, the + following script echoes the Scheme list of its arguments. + + #! /somewhere/tinyscheme -1 + (display *args*) + + The -c flag permits execution of arbitrary Scheme code. + + + Error Handling + -------------- + + Errors are recovered from without damage. The user can install his + own handler for system errors, by defining *error-hook*. Defining + to '() gives the default behavior, which is equivalent to "error". + USE_ERROR_HOOK must be defined. + + A simple exception handling mechanism can be found in "init.scm". + A new syntactic form is introduced: + + (catch + ... ) + + "Catch" establishes a scope spanning multiple call-frames + until another "catch" is encountered. + + Exceptions are thrown with: + + (throw "message") + + If used outside a (catch ...), reverts to (error "message"). + + Example of use: + + (define (foo x) (write x) (newline) (/ x 0)) + + (catch (begin (display "Error!\n") 0) + (write "Before foo ... ") + (foo 5) + (write "After foo")) + + The exception mechanism can be used even by system errors, by + + (define *error-hook* throw) + + which makes use of the error hook described above. + + If necessary, the user can devise his own exception mechanism with + tagged exceptions etc. + + + Reader extensions + ----------------- + + When encountering an unknown character after '#', the user-specified + procedure *sharp-hook* (if any), is called to read the expression. + This can be used to extend the reader to handle user-defined constants + or whatever. It should be a procedure without arguments, reading from + the current input port (which will be the load-port). + + + Colon Qualifiers - Packages + --------------------------- + + When USE_COLON_HOOK=1: + The lexer now recognizes the construction :: and + transforms it in the following manner (T is the transformation function): + + T(::) = (*colon-hook* 'T() ) + + where is a symbol not containing any double-colons. + + As the definition is recursive, qualifiers can be nested. + The user can define his own *colon-hook*, to handle qualified names. + By default, "init.scm" defines *colon-hook* as EVAL. Consequently, + the qualifier must denote a Scheme environment, such as one returned + by (interaction-environment). "Init.scm" defines a new syntantic form, + PACKAGE, as a simple example. It is used like this: + + (define toto + (package + (define foo 1) + (define bar +))) + + foo ==> Error, "foo" undefined + (eval 'foo) ==> Error, "foo" undefined + (eval 'foo toto) ==> 1 + toto::foo ==> 1 + ((eval 'bar toto) 2 (eval 'foo toto)) ==> 3 + (toto::bar 2 toto::foo) ==> 3 + (eval (bar 2 foo) toto) ==> 3 + + If the user installs another package infrastructure, he must define + a new 'package' procedure or macro to retain compatibility with supplied + code. + + Note: Older versions used ':' as a qualifier. Unfortunately, the use + of ':' as a pseudo-qualifier in existing code (i.e. SLIB) essentially + precludes its use as a real qualifier. + + + + + + + + diff --git a/bootstrap/tinyscheme-1.41/MiniSCHEMETribute.txt b/bootstrap/tinyscheme-1.41/MiniSCHEMETribute.txt new file mode 100644 index 0000000..709a53f --- /dev/null +++ b/bootstrap/tinyscheme-1.41/MiniSCHEMETribute.txt @@ -0,0 +1,88 @@ + TinyScheme would not exist if it wasn't for MiniScheme. I had just + written the HTTP server for Ovrimos SQL Server, and I was lamenting the + lack of a scripting language. Server-side Javascript would have been the + preferred solution, had there been a Javascript interpreter I could + lay my hands on. But there weren't. Perl would have been another solution, + but it was probably ten times bigger that the program it was supposed to + be embedded in. There would also be thorny licencing issues. + + So, the obvious thing to do was find a trully small interpreter. Forth + was a language I had once quasi-implemented, but the difficulty of + handling dynamic data and the weirdness of the language put me off. I then + looked around for a LISP interpreter, the next thing I knew was easy to + implement. Alas, the LeLisp I knew from my days in UPMC (Universite Pierre + et Marie Curie) had given way to Common Lisp, a megalith of a language! + Then my search lead me to Scheme, a language I knew was very orthogonal + and clean. When I found Mini-Scheme, a single C file of some 2400 loc, I + fell in love with it! What if it lacked floating-point numbers and + strings! The rest, as they say, is history. + + Below are the original credits. Don't email Akira KIDA, the address has + changed. + + ---------- Mini-Scheme Interpreter Version 0.85 ---------- + + coded by Atsushi Moriwaki (11/5/1989) + + E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp + + THIS SOFTWARE IS IN THE PUBLIC DOMAIN + ------------------------------------ + This software is completely free to copy, modify and/or re-distribute. + But I would appreciate it if you left my name on the code as the author. + + This version has been modified by R.C. Secrist. + + Mini-Scheme is now maintained by Akira KIDA. + + This is a revised and modified version by Akira KIDA. + current version is 0.85k4 (15 May 1994) + + Please send suggestions, bug reports and/or requests to: + + + + Features compared to MiniSCHEME + ------------------------------- + + All code is now reentrant. Interpreter state is held in a 'scheme' + struct, and many interpreters can coexist in the same program, possibly + in different threads. The user can specify user-defined memory allocation + primitives. (see "Programmer's Reference") + + The reader is more consistent. + + Strings, characters and flonums are supported. (see "Types") + + Files being loaded can be nested up to some depth. + + R5RS I/O is there, plus String Ports. (see "Scheme Reference","I/O") + + Vectors exist. + + As a standalone application, it supports command-line arguments. + (see "Standalone") + + Running out of memory is now handled. + + The user can add foreign functions in C. (see "Foreign Functions") + + The code has been changed slightly, core functions have been moved + to the library, behavior has been aligned with R5RS etc. + + Support has been added for user-defined error recovery. + (see "Error Handling") + + Support has been added for modular programming. + (see "Colon Qualifiers - Packages") + + To enable this, EVAL has changed internally, and can + now take two arguments, as per R5RS. Environments are supported. + (see "Colon Qualifiers - Packages") + + Promises are now evaluated once only. + + (macro (foo form) ...) is now equivalent to (macro foo (lambda(form) ...)) + + The reader can be extended using new #-expressions + (see "Reader extensions") diff --git a/bootstrap/tinyscheme-1.41/dynload.c b/bootstrap/tinyscheme-1.41/dynload.c new file mode 100644 index 0000000..563bbd8 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/dynload.c @@ -0,0 +1,146 @@ +/* dynload.c Dynamic Loader for TinyScheme */ +/* Original Copyright (c) 1999 Alexander Shendi */ +/* Modifications for NT and dl_* interface, scm_load_ext: D. Souflis */ +/* Refurbished by Stephen Gildea */ + +#define _SCHEME_SOURCE +#include "dynload.h" +#include +#include +#include + +#ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +#endif + +static void make_filename(const char *name, char *filename); +static void make_init_fn(const char *name, char *init_fn); + +#ifdef _WIN32 +# include +#else +typedef void *HMODULE; +typedef void (*FARPROC)(); +#define SUN_DL +#include +#endif + +#ifdef _WIN32 + +#define PREFIX "" +#define SUFFIX ".dll" + + static void display_w32_error_msg(const char *additional_message) + { + LPVOID msg_buf; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, GetLastError(), 0, + (LPTSTR)&msg_buf, 0, NULL); + fprintf(stderr, "scheme load-extension: %s: %s", additional_message, msg_buf); + LocalFree(msg_buf); + } + +static HMODULE dl_attach(const char *module) { + HMODULE dll = LoadLibrary(module); + if (!dll) display_w32_error_msg(module); + return dll; +} + +static FARPROC dl_proc(HMODULE mo, const char *proc) { + FARPROC procedure = GetProcAddress(mo,proc); + if (!procedure) display_w32_error_msg(proc); + return procedure; +} + +static void dl_detach(HMODULE mo) { + (void)FreeLibrary(mo); +} + +#elif defined(SUN_DL) + +#include + +#define PREFIX "lib" +#define SUFFIX ".so" + +static HMODULE dl_attach(const char *module) { + HMODULE so=dlopen(module,RTLD_LAZY); + if(!so) { + fprintf(stderr, "Error loading scheme extension \"%s\": %s\n", module, dlerror()); + } + return so; +} + +static FARPROC dl_proc(HMODULE mo, const char *proc) { + const char *errmsg; + FARPROC fp=(FARPROC)dlsym(mo,proc); + if ((errmsg = dlerror()) == 0) { + return fp; + } + fprintf(stderr, "Error initializing scheme module \"%s\": %s\n", proc, errmsg); + return 0; +} + +static void dl_detach(HMODULE mo) { + (void)dlclose(mo); +} +#endif + +pointer scm_load_ext(scheme *sc, pointer args) +{ + pointer first_arg; + pointer retval; + char filename[MAXPATHLEN], init_fn[MAXPATHLEN+6]; + char *name; + HMODULE dll_handle; + void (*module_init)(scheme *sc); + + if ((args != sc->NIL) && is_string((first_arg = pair_car(args)))) { + name = string_value(first_arg); + make_filename(name,filename); + make_init_fn(name,init_fn); + dll_handle = dl_attach(filename); + if (dll_handle == 0) { + retval = sc -> F; + } + else { + module_init = (void(*)(scheme *))dl_proc(dll_handle, init_fn); + if (module_init != 0) { + (*module_init)(sc); + retval = sc -> T; + } + else { + retval = sc->F; + } + } + } + else { + retval = sc -> F; + } + + return(retval); +} + +static void make_filename(const char *name, char *filename) { + strcpy(filename,name); + strcat(filename,SUFFIX); +} + +static void make_init_fn(const char *name, char *init_fn) { + const char *p=strrchr(name,'/'); + if(p==0) { + p=name; + } else { + p++; + } + strcpy(init_fn,"init_"); + strcat(init_fn,p); +} + + +/* +Local variables: +c-file-style: "k&r" +End: +*/ diff --git a/bootstrap/tinyscheme-1.41/dynload.h b/bootstrap/tinyscheme-1.41/dynload.h new file mode 100644 index 0000000..71dbbf4 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/dynload.h @@ -0,0 +1,12 @@ +/* dynload.h */ +/* Original Copyright (c) 1999 Alexander Shendi */ +/* Modifications for NT and dl_* interface: D. Souflis */ + +#ifndef DYNLOAD_H +#define DYNLOAD_H + +#include "scheme-private.h" + +SCHEME_EXPORT pointer scm_load_ext(scheme *sc, pointer arglist); + +#endif diff --git a/bootstrap/tinyscheme-1.41/hack.txt b/bootstrap/tinyscheme-1.41/hack.txt new file mode 100644 index 0000000..379787c --- /dev/null +++ b/bootstrap/tinyscheme-1.41/hack.txt @@ -0,0 +1,244 @@ + + How to hack TinyScheme + ---------------------- + + TinyScheme is easy to learn and modify. It is structured like a + meta-interpreter, only it is written in C. All data are Scheme + objects, which facilitates both understanding/modifying the + code and reifying the interpreter workings. + + In place of a dry description, we will pace through the addition + of a useful new datatype: garbage-collected memory blocks. + The interface will be: + + (make-block []) makes a new block of the specified size + optionally filling it with a specified byte + (block? ) + (block-length ) + (block-ref ) retrieves byte at location + (block-set! ) modifies byte at location + + In the sequel, lines that begin with '>' denote lines to add to the + code. Lines that begin with '|' are just citations of existing code. + Lines that begin with X denote lines to be removed from the code. + + First of all, we need to assign a typeid to our new type. Typeids + in TinyScheme are small integers declared in the scheme_types enum + located near the top of the scheme.c file; it begins with T_STRING. + Add a new entry at the end, say T_MEMBLOCK. Remember to adjust the + value of T_LAST_SYTEM_TYPE when adding new entries. There can be at + most 31 types, but you don't have to worry about that limit yet. + +| T_ENVIRONMENT=14, +X T_LAST_SYSTEM_TYPE=14 +> T_MEMBLOCK=15, +> T_LAST_SYSTEM_TYPE=15 +| }; + + + Then, some helper macros would be useful. Go to where is_string() + and the rest are defined and add: + +> INTERFACE INLINE int is_memblock(pointer p) { return (type(p)==T_MEMBLOCK); } + + This actually is a function, because it is meant to be exported by + scheme.h. If no foreign function will ever manipulate a memory block, + you can instead define it as a macro: + +> #define is_memblock(p) (type(p)==T_MEMBLOCK) + + Then we make space for the new type in the main data structure: + struct cell. As it happens, the _string part of the union _object + (that is used to hold character strings) has two fields that suit us: + +| struct { +| char *_svalue; +| int _keynum; +| } _string; + + We can use _svalue to hold the actual pointer and _keynum to hold its + length. If we couln't reuse existing fields, we could always add other + alternatives in union _object. + + We then proceed to write the function that actually makes a new block. + For conformance reasons, we name it mk_memblock + +> static pointer mk_memblock(scheme *sc, int len, char fill) { +> pointer x; +> char *p=(char*)sc->malloc(len); +> +> if(p==0) { +> return sc->NIL; +> } +> x = get_cell(sc, sc->NIL, sc->NIL); +> +> typeflag(x) = T_MEMBLOCK|T_ATOM; +> strvalue(x)=p; +> keynum(x)=len; +> memset(p,fill,len); +> return (x); +> } + + The memory used by the MEMBLOCK will have to be freed when the cell + is reclaimed during garbage collection. There is a placeholder for + that staff, function finalize_cell(), currently handling strings only. + +| static void finalize_cell(scheme *sc, pointer a) { +| if(is_string(a)) { +| sc->free(strvalue(a)); +> } else if(is_memblock(a)) { +> sc->free(strvalue(a)); +| } else if(is_port(a)) { + + There are no MEMBLOCK literals, so we don't concern ourselves with + the READER part (yet!). We must cater to the PRINTER, though. We + add one case more in atom2str(). + +| } else if (iscontinuation(l)) { +| p = "#"; +> } else if (is_memblock(l)) { +> p = "#"; +| } else { + + Whenever a MEMBLOCK is displayed, it will look like that. + Now, we must add the interface functions: constructor, predicate, + accessor, modifier. We must in fact create new op-codes for the virtual + machine underlying TinyScheme. Since version 1.30, TinyScheme uses + macros and a single source text to keep the enums and the dispatch table + in sync. The op-codes are defined in the opdefines.h file with one line + for each op-code. The lines in the file have six columns between the + starting _OPDEF( and ending ): A, B, C, D, E, and OP. + Note that this file uses unusually long lines to accomodate all the + information; adjust your editor to handle this. + + The purpose of the columns is: + - Column A is the name of the subroutine that handles the op-code. + - Column B is the name of the op-code function. + - Columns C and D are the minimum and maximum number of arguments + that are accepted by the op-code. + - Column E is a set of flags that tells the interpreter the type of + each of the arguments expected by the op-code. + - Column OP is used in the scheme_opcodes enum located in the + scheme-private.h file. + + Op-codes are really just tags for a huge C switch, only this switch + is broken up in to a number of different opexe_X functions. The + correspondence is made in table "dispatch_table". There, we assign + the new op-codes to opexe_2, where the equivalent ones for vectors + are situated. We also assign a name for them, and specify the minimum + and maximum arity (number of expected arguments). INF_ARG as a maximum + arity means "unlimited". + + For reasons of consistency, we add the new op-codes right after those + for vectors: + +| _OP_DEF(opexe_2, "vector-set!", 3, 3, TST_VECTOR TST_NATURAL TST_ANY, OP_VECSET ) +> _OP_DEF(opexe_2, "make-block", 1, 2, TST_NATURAL TST_CHAR, OP_MKBLOCK ) +> _OP_DEF(opexe_2, "block-length", 1, 1, T_MEMBLOCK, OP_BLOCKLEN ) +> _OP_DEF(opexe_2, "block-ref", 2, 2, T_MEMBLOCK TST_NATURAL, OP_BLOCKREF ) +> _OP_DEF(opexe_2, "block-set!", 1, 1, T_MEMBLOCK TST_NATURAL TST_CHAR, OP_BLOCKSET ) +| _OP_DEF(opexe_3, "not", 1, 1, TST_NONE, OP_NOT ) + + We add the predicate along with the other predicates in opexe_3: + +| _OP_DEF(opexe_3, "vector?", 1, 1, TST_ANY, OP_VECTORP ) +> _OP_DEF(opexe_3, "block?", 1, 1, TST_ANY, OP_BLOCKP ) +| _OP_DEF(opexe_3, "eq?", 2, 2, TST_ANY, OP_EQ ) + + All that remains is to write the actual code to do the processing and + add it to the switch statement in opexe_2, after the OP_VECSET case. + +> case OP_MKBLOCK: { /* make-block */ +> int fill=0; +> int len; +> +> if(!isnumber(car(sc->args))) { +> Error_1(sc,"make-block: not a number:",car(sc->args)); +> } +> len=ivalue(car(sc->args)); +> if(len<=0) { +> Error_1(sc,"make-block: not positive:",car(sc->args)); +> } +> +> if(cdr(sc->args)!=sc->NIL) { +> if(!isnumber(cadr(sc->args)) || ivalue(cadr(sc->args))<0) { +> Error_1(sc,"make-block: not a positive number:",cadr(sc->args)); +> } +> fill=charvalue(cadr(sc->args))%255; +> } +> s_return(sc,mk_memblock(sc,len,(char)fill)); +> } +> +> case OP_BLOCKLEN: /* block-length */ +> if(!ismemblock(car(sc->args))) { +> Error_1(sc,"block-length: not a memory block:",car(sc->args)); +> } +> s_return(sc,mk_integer(sc,keynum(car(sc->args)))); +> +> case OP_BLOCKREF: { /* block-ref */ +> char *str; +> int index; +> +> if(!ismemblock(car(sc->args))) { +> Error_1(sc,"block-ref: not a memory block:",car(sc->args)); +> } +> str=strvalue(car(sc->args)); +> +> if(cdr(sc->args)==sc->NIL) { +> Error_0(sc,"block-ref: needs two arguments"); +> } +> if(!isnumber(cadr(sc->args))) { +> Error_1(sc,"block-ref: not a number:",cadr(sc->args)); +> } +> index=ivalue(cadr(sc->args)); +> +> if(index<0 || index>=keynum(car(sc->args))) { +> Error_1(sc,"block-ref: out of bounds:",cadr(sc->args)); +> } +> +> s_return(sc,mk_integer(sc,str[index])); +> } +> +> case OP_BLOCKSET: { /* block-set! */ +> char *str; +> int index; +> int c; +> +> if(!ismemblock(car(sc->args))) { +> Error_1(sc,"block-set!: not a memory block:",car(sc->args)); +> } +> if(isimmutable(car(sc->args))) { +> Error_1(sc,"block-set!: unable to alter immutable memory block:",car(sc->args)); +> } +> str=strvalue(car(sc->args)); +> +> if(cdr(sc->args)==sc->NIL) { +> Error_0(sc,"block-set!: needs three arguments"); +> } +> if(!isnumber(cadr(sc->args))) { +> Error_1(sc,"block-set!: not a number:",cadr(sc->args)); +> } +> index=ivalue(cadr(sc->args)); +> if(index<0 || index>=keynum(car(sc->args))) { +> Error_1(sc,"block-set!: out of bounds:",cadr(sc->args)); +> } +> +> if(cddr(sc->args)==sc->NIL) { +> Error_0(sc,"block-set!: needs three arguments"); +> } +> if(!isinteger(caddr(sc->args))) { +> Error_1(sc,"block-set!: not an integer:",caddr(sc->args)); +> } +> c=ivalue(caddr(sc->args))%255; +> +> str[index]=(char)c; +> s_return(sc,car(sc->args)); +> } + + Finally, do the same for the predicate in opexe_3. + +| case OP_VECTORP: /* vector? */ +| s_retbool(is_vector(car(sc->args))); +> case OP_BLOCKP: /* block? */ +> s_retbool(is_memblock(car(sc->args))); +| case OP_EQ: /* eq? */ diff --git a/bootstrap/tinyscheme-1.41/init.scm b/bootstrap/tinyscheme-1.41/init.scm new file mode 100644 index 0000000..196356a --- /dev/null +++ b/bootstrap/tinyscheme-1.41/init.scm @@ -0,0 +1,716 @@ +; Initialization file for TinySCHEME 1.41 + +; Per R5RS, up to four deep compositions should be defined +(define (caar x) (car (car x))) +(define (cadr x) (car (cdr x))) +(define (cdar x) (cdr (car x))) +(define (cddr x) (cdr (cdr x))) +(define (caaar x) (car (car (car x)))) +(define (caadr x) (car (car (cdr x)))) +(define (cadar x) (car (cdr (car x)))) +(define (caddr x) (car (cdr (cdr x)))) +(define (cdaar x) (cdr (car (car x)))) +(define (cdadr x) (cdr (car (cdr x)))) +(define (cddar x) (cdr (cdr (car x)))) +(define (cdddr x) (cdr (cdr (cdr x)))) +(define (caaaar x) (car (car (car (car x))))) +(define (caaadr x) (car (car (car (cdr x))))) +(define (caadar x) (car (car (cdr (car x))))) +(define (caaddr x) (car (car (cdr (cdr x))))) +(define (cadaar x) (car (cdr (car (car x))))) +(define (cadadr x) (car (cdr (car (cdr x))))) +(define (caddar x) (car (cdr (cdr (car x))))) +(define (cadddr x) (car (cdr (cdr (cdr x))))) +(define (cdaaar x) (cdr (car (car (car x))))) +(define (cdaadr x) (cdr (car (car (cdr x))))) +(define (cdadar x) (cdr (car (cdr (car x))))) +(define (cdaddr x) (cdr (car (cdr (cdr x))))) +(define (cddaar x) (cdr (cdr (car (car x))))) +(define (cddadr x) (cdr (cdr (car (cdr x))))) +(define (cdddar x) (cdr (cdr (cdr (car x))))) +(define (cddddr x) (cdr (cdr (cdr (cdr x))))) + +;;;; Utility to ease macro creation +(define (macro-expand form) + ((eval (get-closure-code (eval (car form)))) form)) + +(define (macro-expand-all form) + (if (macro? form) + (macro-expand-all (macro-expand form)) + form)) + +(define *compile-hook* macro-expand-all) + + +(macro (unless form) + `(if (not ,(cadr form)) (begin ,@(cddr form)))) + +(macro (when form) + `(if ,(cadr form) (begin ,@(cddr form)))) + +; DEFINE-MACRO Contributed by Andy Gaynor +(macro (define-macro dform) + (if (symbol? (cadr dform)) + `(macro ,@(cdr dform)) + (let ((form (gensym))) + `(macro (,(caadr dform) ,form) + (apply (lambda ,(cdadr dform) ,@(cddr dform)) (cdr ,form)))))) + +; Utilities for math. Notice that inexact->exact is primitive, +; but exact->inexact is not. +(define exact? integer?) +(define (inexact? x) (and (real? x) (not (integer? x)))) +(define (even? n) (= (remainder n 2) 0)) +(define (odd? n) (not (= (remainder n 2) 0))) +(define (zero? n) (= n 0)) +(define (positive? n) (> n 0)) +(define (negative? n) (< n 0)) +(define complex? number?) +(define rational? real?) +(define (abs n) (if (>= n 0) n (- n))) +(define (exact->inexact n) (* n 1.0)) +(define (<> n1 n2) (not (= n1 n2))) + +; min and max must return inexact if any arg is inexact; use (+ n 0.0) +(define (max . lst) + (foldr (lambda (a b) + (if (> a b) + (if (exact? b) a (+ a 0.0)) + (if (exact? a) b (+ b 0.0)))) + (car lst) (cdr lst))) +(define (min . lst) + (foldr (lambda (a b) + (if (< a b) + (if (exact? b) a (+ a 0.0)) + (if (exact? a) b (+ b 0.0)))) + (car lst) (cdr lst))) + +(define (succ x) (+ x 1)) +(define (pred x) (- x 1)) +(define gcd + (lambda a + (if (null? a) + 0 + (let ((aa (abs (car a))) + (bb (abs (cadr a)))) + (if (= bb 0) + aa + (gcd bb (remainder aa bb))))))) +(define lcm + (lambda a + (if (null? a) + 1 + (let ((aa (abs (car a))) + (bb (abs (cadr a)))) + (if (or (= aa 0) (= bb 0)) + 0 + (abs (* (quotient aa (gcd aa bb)) bb))))))) + + +(define (string . charlist) + (list->string charlist)) + +(define (list->string charlist) + (let* ((len (length charlist)) + (newstr (make-string len)) + (fill-string! + (lambda (str i len charlist) + (if (= i len) + str + (begin (string-set! str i (car charlist)) + (fill-string! str (+ i 1) len (cdr charlist))))))) + (fill-string! newstr 0 len charlist))) + +(define (string-fill! s e) + (let ((n (string-length s))) + (let loop ((i 0)) + (if (= i n) + s + (begin (string-set! s i e) (loop (succ i))))))) + +(define (string->list s) + (let loop ((n (pred (string-length s))) (l '())) + (if (= n -1) + l + (loop (pred n) (cons (string-ref s n) l))))) + +(define (string-copy str) + (string-append str)) + +(define (string->anyatom str pred) + (let* ((a (string->atom str))) + (if (pred a) a + (error "string->xxx: not a xxx" a)))) + +(define (string->number str . base) + (let ((n (string->atom str (if (null? base) 10 (car base))))) + (if (number? n) n #f))) + +(define (anyatom->string n pred) + (if (pred n) + (atom->string n) + (error "xxx->string: not a xxx" n))) + +(define (number->string n . base) + (atom->string n (if (null? base) 10 (car base)))) + + +(define (char-cmp? cmp a b) + (cmp (char->integer a) (char->integer b))) +(define (char-ci-cmp? cmp a b) + (cmp (char->integer (char-downcase a)) (char->integer (char-downcase b)))) + +(define (char=? a b) (char-cmp? = a b)) +(define (char? a b) (char-cmp? > a b)) +(define (char<=? a b) (char-cmp? <= a b)) +(define (char>=? a b) (char-cmp? >= a b)) + +(define (char-ci=? a b) (char-ci-cmp? = a b)) +(define (char-ci? a b) (char-ci-cmp? > a b)) +(define (char-ci<=? a b) (char-ci-cmp? <= a b)) +(define (char-ci>=? a b) (char-ci-cmp? >= a b)) + +; Note the trick of returning (cmp x y) +(define (string-cmp? chcmp cmp a b) + (let ((na (string-length a)) (nb (string-length b))) + (let loop ((i 0)) + (cond + ((= i na) + (if (= i nb) (cmp 0 0) (cmp 0 1))) + ((= i nb) + (cmp 1 0)) + ((chcmp = (string-ref a i) (string-ref b i)) + (loop (succ i))) + (else + (chcmp cmp (string-ref a i) (string-ref b i))))))) + + +(define (string=? a b) (string-cmp? char-cmp? = a b)) +(define (string? a b) (string-cmp? char-cmp? > a b)) +(define (string<=? a b) (string-cmp? char-cmp? <= a b)) +(define (string>=? a b) (string-cmp? char-cmp? >= a b)) + +(define (string-ci=? a b) (string-cmp? char-ci-cmp? = a b)) +(define (string-ci? a b) (string-cmp? char-ci-cmp? > a b)) +(define (string-ci<=? a b) (string-cmp? char-ci-cmp? <= a b)) +(define (string-ci>=? a b) (string-cmp? char-ci-cmp? >= a b)) + +(define (list . x) x) + +(define (foldr f x lst) + (if (null? lst) + x + (foldr f (f x (car lst)) (cdr lst)))) + +(define (unzip1-with-cdr . lists) + (unzip1-with-cdr-iterative lists '() '())) + +(define (unzip1-with-cdr-iterative lists cars cdrs) + (if (null? lists) + (cons cars cdrs) + (let ((car1 (caar lists)) + (cdr1 (cdar lists))) + (unzip1-with-cdr-iterative + (cdr lists) + (append cars (list car1)) + (append cdrs (list cdr1)))))) + +(define (map proc . lists) + (if (null? lists) + (apply proc) + (if (null? (car lists)) + '() + (let* ((unz (apply unzip1-with-cdr lists)) + (cars (car unz)) + (cdrs (cdr unz))) + (cons (apply proc cars) (apply map (cons proc cdrs))))))) + +(define (for-each proc . lists) + (if (null? lists) + (apply proc) + (if (null? (car lists)) + #t + (let* ((unz (apply unzip1-with-cdr lists)) + (cars (car unz)) + (cdrs (cdr unz))) + (apply proc cars) (apply map (cons proc cdrs)))))) + +(define (list-tail x k) + (if (zero? k) + x + (list-tail (cdr x) (- k 1)))) + +(define (list-ref x k) + (car (list-tail x k))) + +(define (last-pair x) + (if (pair? (cdr x)) + (last-pair (cdr x)) + x)) + +(define (head stream) (car stream)) + +(define (tail stream) (force (cdr stream))) + +(define (vector-equal? x y) + (and (vector? x) (vector? y) (= (vector-length x) (vector-length y)) + (let ((n (vector-length x))) + (let loop ((i 0)) + (if (= i n) + #t + (and (equal? (vector-ref x i) (vector-ref y i)) + (loop (succ i)))))))) + +(define (list->vector x) + (apply vector x)) + +(define (vector-fill! v e) + (let ((n (vector-length v))) + (let loop ((i 0)) + (if (= i n) + v + (begin (vector-set! v i e) (loop (succ i))))))) + +(define (vector->list v) + (let loop ((n (pred (vector-length v))) (l '())) + (if (= n -1) + l + (loop (pred n) (cons (vector-ref v n) l))))) + +;; The following quasiquote macro is due to Eric S. Tiedemann. +;; Copyright 1988 by Eric S. Tiedemann; all rights reserved. +;; +;; Subsequently modified to handle vectors: D. Souflis + +(macro + quasiquote + (lambda (l) + (define (mcons f l r) + (if (and (pair? r) + (eq? (car r) 'quote) + (eq? (car (cdr r)) (cdr f)) + (pair? l) + (eq? (car l) 'quote) + (eq? (car (cdr l)) (car f))) + (if (or (procedure? f) (number? f) (string? f)) + f + (list 'quote f)) + (if (eqv? l vector) + (apply l (eval r)) + (list 'cons l r) + ))) + (define (mappend f l r) + (if (or (null? (cdr f)) + (and (pair? r) + (eq? (car r) 'quote) + (eq? (car (cdr r)) '()))) + l + (list 'append l r))) + (define (foo level form) + (cond ((not (pair? form)) + (if (or (procedure? form) (number? form) (string? form)) + form + (list 'quote form)) + ) + ((eq? 'quasiquote (car form)) + (mcons form ''quasiquote (foo (+ level 1) (cdr form)))) + (#t (if (zero? level) + (cond ((eq? (car form) 'unquote) (car (cdr form))) + ((eq? (car form) 'unquote-splicing) + (error "Unquote-splicing wasn't in a list:" + form)) + ((and (pair? (car form)) + (eq? (car (car form)) 'unquote-splicing)) + (mappend form (car (cdr (car form))) + (foo level (cdr form)))) + (#t (mcons form (foo level (car form)) + (foo level (cdr form))))) + (cond ((eq? (car form) 'unquote) + (mcons form ''unquote (foo (- level 1) + (cdr form)))) + ((eq? (car form) 'unquote-splicing) + (mcons form ''unquote-splicing + (foo (- level 1) (cdr form)))) + (#t (mcons form (foo level (car form)) + (foo level (cdr form))))))))) + (foo 0 (car (cdr l))))) + +;;;;;Helper for the dynamic-wind definition. By Tom Breton (Tehom) +(define (shared-tail x y) + (let ((len-x (length x)) + (len-y (length y))) + (define (shared-tail-helper x y) + (if + (eq? x y) + x + (shared-tail-helper (cdr x) (cdr y)))) + + (cond + ((> len-x len-y) + (shared-tail-helper + (list-tail x (- len-x len-y)) + y)) + ((< len-x len-y) + (shared-tail-helper + x + (list-tail y (- len-y len-x)))) + (#t (shared-tail-helper x y))))) + +;;;;;Dynamic-wind by Tom Breton (Tehom) + +;;Guarded because we must only eval this once, because doing so +;;redefines call/cc in terms of old call/cc +(unless (defined? 'dynamic-wind) + (let + ;;These functions are defined in the context of a private list of + ;;pairs of before/after procs. + ( (*active-windings* '()) + ;;We'll define some functions into the larger environment, so + ;;we need to know it. + (outer-env (current-environment))) + + ;;Poor-man's structure operations + (define before-func car) + (define after-func cdr) + (define make-winding cons) + + ;;Manage active windings + (define (activate-winding! new) + ((before-func new)) + (set! *active-windings* (cons new *active-windings*))) + (define (deactivate-top-winding!) + (let ((old-top (car *active-windings*))) + ;;Remove it from the list first so it's not active during its + ;;own exit. + (set! *active-windings* (cdr *active-windings*)) + ((after-func old-top)))) + + (define (set-active-windings! new-ws) + (unless (eq? new-ws *active-windings*) + (let ((shared (shared-tail new-ws *active-windings*))) + + ;;Define the looping functions. + ;;Exit the old list. Do deeper ones last. Don't do + ;;any shared ones. + (define (pop-many) + (unless (eq? *active-windings* shared) + (deactivate-top-winding!) + (pop-many))) + ;;Enter the new list. Do deeper ones first so that the + ;;deeper windings will already be active. Don't do any + ;;shared ones. + (define (push-many new-ws) + (unless (eq? new-ws shared) + (push-many (cdr new-ws)) + (activate-winding! (car new-ws)))) + + ;;Do it. + (pop-many) + (push-many new-ws)))) + + ;;The definitions themselves. + (eval + `(define call-with-current-continuation + ;;It internally uses the built-in call/cc, so capture it. + ,(let ((old-c/cc call-with-current-continuation)) + (lambda (func) + ;;Use old call/cc to get the continuation. + (old-c/cc + (lambda (continuation) + ;;Call func with not the continuation itself + ;;but a procedure that adjusts the active + ;;windings to what they were when we made + ;;this, and only then calls the + ;;continuation. + (func + (let ((current-ws *active-windings*)) + (lambda (x) + (set-active-windings! current-ws) + (continuation x))))))))) + outer-env) + ;;We can't just say "define (dynamic-wind before thunk after)" + ;;because the lambda it's defined to lives in this environment, + ;;not in the global environment. + (eval + `(define dynamic-wind + ,(lambda (before thunk after) + ;;Make a new winding + (activate-winding! (make-winding before after)) + (let ((result (thunk))) + ;;Get rid of the new winding. + (deactivate-top-winding!) + ;;The return value is that of thunk. + result))) + outer-env))) + +(define call/cc call-with-current-continuation) + + +;;;;; atom? and equal? written by a.k + +;;;; atom? +(define (atom? x) + (not (pair? x))) + +;;;; equal? +(define (equal? x y) + (cond + ((pair? x) + (and (pair? y) + (equal? (car x) (car y)) + (equal? (cdr x) (cdr y)))) + ((vector? x) + (and (vector? y) (vector-equal? x y))) + ((string? x) + (and (string? y) (string=? x y))) + (else (eqv? x y)))) + +;;;; (do ((var init inc) ...) (endtest result ...) body ...) +;; +(macro do + (lambda (do-macro) + (apply (lambda (do vars endtest . body) + (let ((do-loop (gensym))) + `(letrec ((,do-loop + (lambda ,(map (lambda (x) + (if (pair? x) (car x) x)) + `,vars) + (if ,(car endtest) + (begin ,@(cdr endtest)) + (begin + ,@body + (,do-loop + ,@(map (lambda (x) + (cond + ((not (pair? x)) x) + ((< (length x) 3) (car x)) + (else (car (cdr (cdr x)))))) + `,vars))))))) + (,do-loop + ,@(map (lambda (x) + (if (and (pair? x) (cdr x)) + (car (cdr x)) + '())) + `,vars))))) + do-macro))) + +;;;; generic-member +(define (generic-member cmp obj lst) + (cond + ((null? lst) #f) + ((cmp obj (car lst)) lst) + (else (generic-member cmp obj (cdr lst))))) + +(define (memq obj lst) + (generic-member eq? obj lst)) +(define (memv obj lst) + (generic-member eqv? obj lst)) +(define (member obj lst) + (generic-member equal? obj lst)) + +;;;; generic-assoc +(define (generic-assoc cmp obj alst) + (cond + ((null? alst) #f) + ((cmp obj (caar alst)) (car alst)) + (else (generic-assoc cmp obj (cdr alst))))) + +(define (assq obj alst) + (generic-assoc eq? obj alst)) +(define (assv obj alst) + (generic-assoc eqv? obj alst)) +(define (assoc obj alst) + (generic-assoc equal? obj alst)) + +(define (acons x y z) (cons (cons x y) z)) + +;;;; Handy for imperative programs +;;;; Used as: (define-with-return (foo x y) .... (return z) ...) +(macro (define-with-return form) + `(define ,(cadr form) + (call/cc (lambda (return) ,@(cddr form))))) + +;;;; Simple exception handling +; +; Exceptions are caught as follows: +; +; (catch (do-something to-recover and-return meaningful-value) +; (if-something goes-wrong) +; (with-these calls)) +; +; "Catch" establishes a scope spanning multiple call-frames +; until another "catch" is encountered. +; +; Exceptions are thrown with: +; +; (throw "message") +; +; If used outside a (catch ...), reverts to (error "message) + +(define *handlers* (list)) + +(define (push-handler proc) + (set! *handlers* (cons proc *handlers*))) + +(define (pop-handler) + (let ((h (car *handlers*))) + (set! *handlers* (cdr *handlers*)) + h)) + +(define (more-handlers?) + (pair? *handlers*)) + +(define (throw . x) + (if (more-handlers?) + (apply (pop-handler)) + (apply error x))) + +(macro (catch form) + (let ((label (gensym))) + `(call/cc (lambda (exit) + (push-handler (lambda () (exit ,(cadr form)))) + (let ((,label (begin ,@(cddr form)))) + (pop-handler) + ,label))))) + +(define *error-hook* throw) + + +;;;;; Definition of MAKE-ENVIRONMENT, to be used with two-argument EVAL + +(macro (make-environment form) + `(apply (lambda () + ,@(cdr form) + (current-environment)))) + +(define-macro (eval-polymorphic x . envl) + (display envl) + (let* ((env (if (null? envl) (current-environment) (eval (car envl)))) + (xval (eval x env))) + (if (closure? xval) + (make-closure (get-closure-code xval) env) + xval))) + +; Redefine this if you install another package infrastructure +; Also redefine 'package' +(define *colon-hook* eval) + +;;;;; I/O + +(define (input-output-port? p) + (and (input-port? p) (output-port? p))) + +(define (close-port p) + (cond + ((input-output-port? p) (close-input-port (close-output-port p))) + ((input-port? p) (close-input-port p)) + ((output-port? p) (close-output-port p)) + (else (throw "Not a port" p)))) + +(define (call-with-input-file s p) + (let ((inport (open-input-file s))) + (if (eq? inport #f) + #f + (let ((res (p inport))) + (close-input-port inport) + res)))) + +(define (call-with-output-file s p) + (let ((outport (open-output-file s))) + (if (eq? outport #f) + #f + (let ((res (p outport))) + (close-output-port outport) + res)))) + +(define (with-input-from-file s p) + (let ((inport (open-input-file s))) + (if (eq? inport #f) + #f + (let ((prev-inport (current-input-port))) + (set-input-port inport) + (let ((res (p))) + (close-input-port inport) + (set-input-port prev-inport) + res))))) + +(define (with-output-to-file s p) + (let ((outport (open-output-file s))) + (if (eq? outport #f) + #f + (let ((prev-outport (current-output-port))) + (set-output-port outport) + (let ((res (p))) + (close-output-port outport) + (set-output-port prev-outport) + res))))) + +(define (with-input-output-from-to-files si so p) + (let ((inport (open-input-file si)) + (outport (open-input-file so))) + (if (not (and inport outport)) + (begin + (close-input-port inport) + (close-output-port outport) + #f) + (let ((prev-inport (current-input-port)) + (prev-outport (current-output-port))) + (set-input-port inport) + (set-output-port outport) + (let ((res (p))) + (close-input-port inport) + (close-output-port outport) + (set-input-port prev-inport) + (set-output-port prev-outport) + res))))) + +; Random number generator (maximum cycle) +(define *seed* 1) +(define (random-next) + (let* ((a 16807) (m 2147483647) (q (quotient m a)) (r (modulo m a))) + (set! *seed* + (- (* a (- *seed* + (* (quotient *seed* q) q))) + (* (quotient *seed* q) r))) + (if (< *seed* 0) (set! *seed* (+ *seed* m))) + *seed*)) +;; SRFI-0 +;; COND-EXPAND +;; Implemented as a macro +(define *features* '(srfi-0)) + +(define-macro (cond-expand . cond-action-list) + (cond-expand-runtime cond-action-list)) + +(define (cond-expand-runtime cond-action-list) + (if (null? cond-action-list) + #t + (if (cond-eval (caar cond-action-list)) + `(begin ,@(cdar cond-action-list)) + (cond-expand-runtime (cdr cond-action-list))))) + +(define (cond-eval-and cond-list) + (foldr (lambda (x y) (and (cond-eval x) (cond-eval y))) #t cond-list)) + +(define (cond-eval-or cond-list) + (foldr (lambda (x y) (or (cond-eval x) (cond-eval y))) #f cond-list)) + +(define (cond-eval condition) + (cond + ((symbol? condition) + (if (member condition *features*) #t #f)) + ((eq? condition #t) #t) + ((eq? condition #f) #f) + (else (case (car condition) + ((and) (cond-eval-and (cdr condition))) + ((or) (cond-eval-or (cdr condition))) + ((not) (if (not (null? (cddr condition))) + (error "cond-expand : 'not' takes 1 argument") + (not (cond-eval (cadr condition))))) + (else (error "cond-expand : unknown operator" (car condition))))))) + +(gc-verbose #f) diff --git a/bootstrap/tinyscheme-1.41/makefile b/bootstrap/tinyscheme-1.41/makefile new file mode 100644 index 0000000..af80d62 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/makefile @@ -0,0 +1,102 @@ +# Makefile for TinyScheme +# Time-stamp: <2002-06-24 14:13:27 gildea> + +# Windows/2000 +#CC = cl -nologo +#DEBUG= -W3 -Z7 -MD +#DL_FLAGS= +#SYS_LIBS= +#Osuf=obj +#SOsuf=dll +#LIBsuf=.lib +#EXE_EXT=.exe +#LD = link -nologo +#LDFLAGS = -debug -map -dll -incremental:no +#LIBPREFIX = +#OUT = -out:$@ +#RM= -del +#AR= echo + +# Unix, generally +CC = gcc -fpic -pedantic -pg +DEBUG=-g -Wall -Wno-char-subscripts -O +Osuf=o +SOsuf=so +LIBsuf=a +EXE_EXT=.exe +LIBPREFIX=lib +OUT = -o $@ +RM= -rm -f +AR= ar crs + +# Linux +LD = gcc -pg +LDFLAGS = -shared +DEBUG=-g -Wno-char-subscripts -O +SYS_LIBS= -ldl -lm +PLATFORM_FEATURES= -DSUN_DL=1 + +# Cygwin +#PLATFORM_FEATURES = -DUSE_STRLWR=0 + +# MinGW/MSYS +ifeq ($(OS),Windows_NT) +CC = gcc -pedantic -Wall -pg +SOsuf=dll +PLATFORM_FEATURES = -DUSE_STRLWR=0 -DTS_BOOTSTRAP_MINGW32 +SYS_LIBS= -lm +RM=rm.cmd /q +endif + +# Mac OS X +#LD = gcc +#LDFLAGS = --dynamiclib +#DEBUG=-g -Wno-char-subscripts -O +#SYS_LIBS= -ldl +#PLATFORM_FEATURES= -DUSE_STRLWR=1 -D__APPLE__=1 -DOSX=1 + + +# Solaris +#SYS_LIBS= -ldl -lc +#Osuf=o +#SOsuf=so +#EXE_EXT= +#LD = ld +#LDFLAGS = -G -Bsymbolic -z text +#LIBPREFIX = lib +#OUT = -o $@ + +FEATURES = $(PLATFORM_FEATURES) -DUSE_DL=1 -DUSE_MATH=1 -DUSE_ASCII_NAMES=0 + +OBJS = scheme.$(Osuf) dynload.$(Osuf) + +LIBTARGET = $(LIBPREFIX)tinyscheme.$(SOsuf) +STATICLIBTARGET = $(LIBPREFIX)tinyscheme.$(LIBsuf) + +all: $(LIBTARGET) $(STATICLIBTARGET) scheme$(EXE_EXT) + +%.$(Osuf): %.c + $(CC) -I. -c $(DEBUG) $(FEATURES) $(DL_FLAGS) $< + +$(LIBTARGET): $(OBJS) + $(LD) $(LDFLAGS) $(OUT) $(OBJS) $(SYS_LIBS) + +scheme$(EXE_EXT): $(OBJS) + $(CC) -o $@ $(DEBUG) $(OBJS) $(SYS_LIBS) + +$(STATICLIBTARGET): $(OBJS) + $(AR) $@ $(OBJS) + +$(OBJS): scheme.h scheme-private.h opdefines.h ../bootstrap-ops-5.h ../bootstrap-ops-5.c +dynload.$(Osuf): dynload.h + +clean: + $(RM) $(OBJS) $(LIBTARGET) $(STATICLIBTARGET) scheme$(EXE_EXT) + $(RM) tinyscheme.ilk tinyscheme.map tinyscheme.pdb tinyscheme.exp + $(RM) scheme.ilk scheme.map scheme.pdb scheme.lib scheme.exp + +TAGS_SRCS = scheme.h scheme.c dynload.h dynload.c + +tags: TAGS +TAGS: $(TAGS_SRCS) + etags $(TAGS_SRCS) diff --git a/bootstrap/tinyscheme-1.41/opdefines.h b/bootstrap/tinyscheme-1.41/opdefines.h new file mode 100644 index 0000000..1513620 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/opdefines.h @@ -0,0 +1,196 @@ + _OP_DEF(opexe_0, "load", 1, 1, TST_STRING, OP_LOAD ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_T0LVL ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_T1LVL ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_READ_INTERNAL ) + _OP_DEF(opexe_0, "gensym", 0, 0, 0, OP_GENSYM ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_VALUEPRINT ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_EVAL ) +#if USE_TRACING + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_REAL_EVAL ) +#endif + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_E0ARGS ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_E1ARGS ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_APPLY ) +#if USE_TRACING + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_REAL_APPLY ) + _OP_DEF(opexe_0, "tracing", 1, 1, TST_NATURAL, OP_TRACING ) +#endif + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DOMACRO ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LAMBDA ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LAMBDA1 ) + _OP_DEF(opexe_0, "make-closure", 1, 2, TST_PAIR TST_ENVIRONMENT, OP_MKCLOSURE ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_QUOTE ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DEF0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DEF1 ) + _OP_DEF(opexe_0, "defined?", 1, 2, TST_SYMBOL TST_ENVIRONMENT, OP_DEFP ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_BEGIN ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_IF0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_IF1 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_SET0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_SET1 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET0 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET1 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET2 ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET0AST ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET1AST ) + _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET2AST ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET0REC ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET1REC ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET2REC ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_COND0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_COND1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_DELAY ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_AND0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_AND1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_OR0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_OR1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_C0STREAM ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_C1STREAM ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_MACRO0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_MACRO1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE0 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE1 ) + _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE2 ) + _OP_DEF(opexe_1, "eval", 1, 2, TST_ANY TST_ENVIRONMENT, OP_PEVAL ) + _OP_DEF(opexe_1, "apply", 1, INF_ARG, TST_NONE, OP_PAPPLY ) + _OP_DEF(opexe_1, "call-with-current-continuation", 1, 1, TST_NONE, OP_CONTINUATION ) +#if USE_MATH + _OP_DEF(opexe_2, "inexact->exact", 1, 1, TST_NUMBER, OP_INEX2EX ) + _OP_DEF(opexe_2, "exp", 1, 1, TST_NUMBER, OP_EXP ) + _OP_DEF(opexe_2, "log", 1, 1, TST_NUMBER, OP_LOG ) + _OP_DEF(opexe_2, "sin", 1, 1, TST_NUMBER, OP_SIN ) + _OP_DEF(opexe_2, "cos", 1, 1, TST_NUMBER, OP_COS ) + _OP_DEF(opexe_2, "tan", 1, 1, TST_NUMBER, OP_TAN ) + _OP_DEF(opexe_2, "asin", 1, 1, TST_NUMBER, OP_ASIN ) + _OP_DEF(opexe_2, "acos", 1, 1, TST_NUMBER, OP_ACOS ) + _OP_DEF(opexe_2, "atan", 1, 2, TST_NUMBER, OP_ATAN ) + _OP_DEF(opexe_2, "sqrt", 1, 1, TST_NUMBER, OP_SQRT ) + _OP_DEF(opexe_2, "expt", 2, 2, TST_NUMBER, OP_EXPT ) + _OP_DEF(opexe_2, "floor", 1, 1, TST_NUMBER, OP_FLOOR ) + _OP_DEF(opexe_2, "ceiling", 1, 1, TST_NUMBER, OP_CEILING ) + _OP_DEF(opexe_2, "truncate", 1, 1, TST_NUMBER, OP_TRUNCATE ) + _OP_DEF(opexe_2, "round", 1, 1, TST_NUMBER, OP_ROUND ) +#endif + _OP_DEF(opexe_2, "+", 0, INF_ARG, TST_NUMBER, OP_ADD ) + _OP_DEF(opexe_2, "-", 1, INF_ARG, TST_NUMBER, OP_SUB ) + _OP_DEF(opexe_2, "*", 0, INF_ARG, TST_NUMBER, OP_MUL ) + _OP_DEF(opexe_2, "/", 1, INF_ARG, TST_NUMBER, OP_DIV ) + _OP_DEF(opexe_2, "quotient", 1, INF_ARG, TST_INTEGER, OP_INTDIV ) + _OP_DEF(opexe_2, "remainder", 2, 2, TST_INTEGER, OP_REM ) + _OP_DEF(opexe_2, "modulo", 2, 2, TST_INTEGER, OP_MOD ) + _OP_DEF(opexe_2, "car", 1, 1, TST_PAIR, OP_CAR ) + _OP_DEF(opexe_2, "cdr", 1, 1, TST_PAIR, OP_CDR ) + _OP_DEF(opexe_2, "cons", 2, 2, TST_NONE, OP_CONS ) + _OP_DEF(opexe_2, "set-car!", 2, 2, TST_PAIR TST_ANY, OP_SETCAR ) + _OP_DEF(opexe_2, "set-cdr!", 2, 2, TST_PAIR TST_ANY, OP_SETCDR ) + _OP_DEF(opexe_2, "char->integer", 1, 1, TST_CHAR, OP_CHAR2INT ) + _OP_DEF(opexe_2, "integer->char", 1, 1, TST_NATURAL, OP_INT2CHAR ) + _OP_DEF(opexe_2, "char-upcase", 1, 1, TST_CHAR, OP_CHARUPCASE ) + _OP_DEF(opexe_2, "char-downcase", 1, 1, TST_CHAR, OP_CHARDNCASE ) + _OP_DEF(opexe_2, "symbol->string", 1, 1, TST_SYMBOL, OP_SYM2STR ) + _OP_DEF(opexe_2, "atom->string", 1, 2, TST_ANY TST_NATURAL, OP_ATOM2STR ) + _OP_DEF(opexe_2, "string->symbol", 1, 1, TST_STRING, OP_STR2SYM ) + _OP_DEF(opexe_2, "string->atom", 1, 2, TST_STRING TST_NATURAL, OP_STR2ATOM ) + _OP_DEF(opexe_2, "make-string", 1, 2, TST_NATURAL TST_CHAR, OP_MKSTRING ) + _OP_DEF(opexe_2, "string-length", 1, 1, TST_STRING, OP_STRLEN ) + _OP_DEF(opexe_2, "string-ref", 2, 2, TST_STRING TST_NATURAL, OP_STRREF ) + _OP_DEF(opexe_2, "string-set!", 3, 3, TST_STRING TST_NATURAL TST_CHAR, OP_STRSET ) + _OP_DEF(opexe_2, "string-append", 0, INF_ARG, TST_STRING, OP_STRAPPEND ) + _OP_DEF(opexe_2, "substring", 2, 3, TST_STRING TST_NATURAL, OP_SUBSTR ) + _OP_DEF(opexe_2, "vector", 0, INF_ARG, TST_NONE, OP_VECTOR ) + _OP_DEF(opexe_2, "make-vector", 1, 2, TST_NATURAL TST_ANY, OP_MKVECTOR ) + _OP_DEF(opexe_2, "vector-length", 1, 1, TST_VECTOR, OP_VECLEN ) + _OP_DEF(opexe_2, "vector-ref", 2, 2, TST_VECTOR TST_NATURAL, OP_VECREF ) + _OP_DEF(opexe_2, "vector-set!", 3, 3, TST_VECTOR TST_NATURAL TST_ANY, OP_VECSET ) + _OP_DEF(opexe_3, "not", 1, 1, TST_NONE, OP_NOT ) + _OP_DEF(opexe_3, "boolean?", 1, 1, TST_NONE, OP_BOOLP ) + _OP_DEF(opexe_3, "eof-object?", 1, 1, TST_NONE, OP_EOFOBJP ) + _OP_DEF(opexe_3, "null?", 1, 1, TST_NONE, OP_NULLP ) + _OP_DEF(opexe_3, "=", 2, INF_ARG, TST_NUMBER, OP_NUMEQ ) + _OP_DEF(opexe_3, "<", 2, INF_ARG, TST_NUMBER, OP_LESS ) + _OP_DEF(opexe_3, ">", 2, INF_ARG, TST_NUMBER, OP_GRE ) + _OP_DEF(opexe_3, "<=", 2, INF_ARG, TST_NUMBER, OP_LEQ ) + _OP_DEF(opexe_3, ">=", 2, INF_ARG, TST_NUMBER, OP_GEQ ) + _OP_DEF(opexe_3, "symbol?", 1, 1, TST_ANY, OP_SYMBOLP ) + _OP_DEF(opexe_3, "number?", 1, 1, TST_ANY, OP_NUMBERP ) + _OP_DEF(opexe_3, "string?", 1, 1, TST_ANY, OP_STRINGP ) + _OP_DEF(opexe_3, "integer?", 1, 1, TST_ANY, OP_INTEGERP ) + _OP_DEF(opexe_3, "real?", 1, 1, TST_ANY, OP_REALP ) + _OP_DEF(opexe_3, "char?", 1, 1, TST_ANY, OP_CHARP ) +#if USE_CHAR_CLASSIFIERS + _OP_DEF(opexe_3, "char-alphabetic?", 1, 1, TST_CHAR, OP_CHARAP ) + _OP_DEF(opexe_3, "char-numeric?", 1, 1, TST_CHAR, OP_CHARNP ) + _OP_DEF(opexe_3, "char-whitespace?", 1, 1, TST_CHAR, OP_CHARWP ) + _OP_DEF(opexe_3, "char-upper-case?", 1, 1, TST_CHAR, OP_CHARUP ) + _OP_DEF(opexe_3, "char-lower-case?", 1, 1, TST_CHAR, OP_CHARLP ) +#endif + _OP_DEF(opexe_3, "port?", 1, 1, TST_ANY, OP_PORTP ) + _OP_DEF(opexe_3, "input-port?", 1, 1, TST_ANY, OP_INPORTP ) + _OP_DEF(opexe_3, "output-port?", 1, 1, TST_ANY, OP_OUTPORTP ) + _OP_DEF(opexe_3, "procedure?", 1, 1, TST_ANY, OP_PROCP ) + _OP_DEF(opexe_3, "pair?", 1, 1, TST_ANY, OP_PAIRP ) + _OP_DEF(opexe_3, "list?", 1, 1, TST_ANY, OP_LISTP ) + _OP_DEF(opexe_3, "environment?", 1, 1, TST_ANY, OP_ENVP ) + _OP_DEF(opexe_3, "vector?", 1, 1, TST_ANY, OP_VECTORP ) + _OP_DEF(opexe_3, "eq?", 2, 2, TST_ANY, OP_EQ ) + _OP_DEF(opexe_3, "eqv?", 2, 2, TST_ANY, OP_EQV ) + _OP_DEF(opexe_4, "force", 1, 1, TST_ANY, OP_FORCE ) + _OP_DEF(opexe_4, 0, 0, 0, 0, OP_SAVE_FORCED ) + _OP_DEF(opexe_4, "write", 1, 2, TST_ANY TST_OUTPORT, OP_WRITE ) + _OP_DEF(opexe_4, "write-char", 1, 2, TST_CHAR TST_OUTPORT, OP_WRITE_CHAR ) + _OP_DEF(opexe_4, "display", 1, 2, TST_ANY TST_OUTPORT, OP_DISPLAY ) + _OP_DEF(opexe_4, "newline", 0, 1, TST_OUTPORT, OP_NEWLINE ) + _OP_DEF(opexe_4, "error", 1, INF_ARG, TST_NONE, OP_ERR0 ) + _OP_DEF(opexe_4, 0, 0, 0, 0, OP_ERR1 ) + _OP_DEF(opexe_4, "reverse", 1, 1, TST_LIST, OP_REVERSE ) + _OP_DEF(opexe_4, "list*", 1, INF_ARG, TST_NONE, OP_LIST_STAR ) + _OP_DEF(opexe_4, "append", 0, INF_ARG, TST_NONE, OP_APPEND ) +#if USE_PLIST + _OP_DEF(opexe_4, "put", 3, 3, TST_NONE, OP_PUT ) + _OP_DEF(opexe_4, "get", 2, 2, TST_NONE, OP_GET ) +#endif + _OP_DEF(opexe_4, "quit", 0, 1, TST_NUMBER, OP_QUIT ) + _OP_DEF(opexe_4, "gc", 0, 0, 0, OP_GC ) + _OP_DEF(opexe_4, "gc-verbose", 0, 1, TST_NONE, OP_GCVERB ) + _OP_DEF(opexe_4, "new-segment", 0, 1, TST_NUMBER, OP_NEWSEGMENT ) + _OP_DEF(opexe_4, "oblist", 0, 0, 0, OP_OBLIST ) + _OP_DEF(opexe_4, "current-input-port", 0, 0, 0, OP_CURR_INPORT ) + _OP_DEF(opexe_4, "current-output-port", 0, 0, 0, OP_CURR_OUTPORT ) + _OP_DEF(opexe_4, "open-input-file", 1, 1, TST_STRING, OP_OPEN_INFILE ) + _OP_DEF(opexe_4, "open-output-file", 1, 1, TST_STRING, OP_OPEN_OUTFILE ) + _OP_DEF(opexe_4, "open-input-output-file", 1, 1, TST_STRING, OP_OPEN_INOUTFILE ) +#if USE_STRING_PORTS + _OP_DEF(opexe_4, "open-input-string", 1, 1, TST_STRING, OP_OPEN_INSTRING ) + _OP_DEF(opexe_4, "open-input-output-string", 1, 1, TST_STRING, OP_OPEN_INOUTSTRING ) + _OP_DEF(opexe_4, "open-output-string", 0, 1, TST_STRING, OP_OPEN_OUTSTRING ) + _OP_DEF(opexe_4, "get-output-string", 1, 1, TST_OUTPORT, OP_GET_OUTSTRING ) +#endif + _OP_DEF(opexe_4, "close-input-port", 1, 1, TST_INPORT, OP_CLOSE_INPORT ) + _OP_DEF(opexe_4, "close-output-port", 1, 1, TST_OUTPORT, OP_CLOSE_OUTPORT ) + _OP_DEF(opexe_4, "interaction-environment", 0, 0, 0, OP_INT_ENV ) + _OP_DEF(opexe_4, "current-environment", 0, 0, 0, OP_CURR_ENV ) + _OP_DEF(opexe_5, "read", 0, 1, TST_INPORT, OP_READ ) + _OP_DEF(opexe_5, "read-char", 0, 1, TST_INPORT, OP_READ_CHAR ) + _OP_DEF(opexe_5, "peek-char", 0, 1, TST_INPORT, OP_PEEK_CHAR ) + _OP_DEF(opexe_5, "char-ready?", 0, 1, TST_INPORT, OP_CHAR_READY ) + _OP_DEF(opexe_5, "set-input-port", 1, 1, TST_INPORT, OP_SET_INPORT ) + _OP_DEF(opexe_5, "set-output-port", 1, 1, TST_OUTPORT, OP_SET_OUTPORT ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDSEXPR ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDLIST ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDDOT ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQUOTE ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQQUOTE ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQQUOTEVEC ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDUNQUOTE ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDUQTSP ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDVEC ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_P0LIST ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_P1LIST ) + _OP_DEF(opexe_5, 0, 0, 0, 0, OP_PVECFROM ) +#include "../bootstrap-ops-5.h" + _OP_DEF(opexe_6, "length", 1, 1, TST_LIST, OP_LIST_LENGTH ) + _OP_DEF(opexe_6, "assq", 2, 2, TST_NONE, OP_ASSQ ) + _OP_DEF(opexe_6, "get-closure-code", 1, 1, TST_NONE, OP_GET_CLOSURE ) + _OP_DEF(opexe_6, "closure?", 1, 1, TST_NONE, OP_CLOSUREP ) + _OP_DEF(opexe_6, "macro?", 1, 1, TST_NONE, OP_MACROP ) +#undef _OP_DEF diff --git a/bootstrap/tinyscheme-1.41/rm.cmd b/bootstrap/tinyscheme-1.41/rm.cmd new file mode 100644 index 0000000..42da587 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/rm.cmd @@ -0,0 +1 @@ +@del %* diff --git a/bootstrap/tinyscheme-1.41/scheme-private.h b/bootstrap/tinyscheme-1.41/scheme-private.h new file mode 100644 index 0000000..423547a --- /dev/null +++ b/bootstrap/tinyscheme-1.41/scheme-private.h @@ -0,0 +1,211 @@ +/* scheme-private.h */ + +#ifndef _SCHEME_PRIVATE_H +#define _SCHEME_PRIVATE_H + +#include "scheme.h" +#include "../bootstrap.h" +/*------------------ Ugly internals -----------------------------------*/ +/*------------------ Of interest only to FFI users --------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +enum scheme_port_kind { + port_free=0, + port_file=1, + port_string=2, + port_srfi6=4, + port_input=16, + port_output=32, + port_saw_EOF=64 +}; + +typedef struct port { + unsigned char kind; + union { + struct { + FILE *file; + int closeit; +#if SHOW_ERROR_LINE + int curr_line; + char *filename; +#endif + } stdio; + struct { + char *start; + char *past_the_end; + char *curr; + } string; + } rep; +} port; + +/* cell structure */ +struct cell { + unsigned int _flag; + union { + struct { + char *_svalue; + int _length; + } _string; + num _number; + port *_port; + foreign_func _ff; + struct { + struct cell *_car; + struct cell *_cdr; + } _cons; + } _object; +}; + +struct scheme { +/* arrays for segments */ +func_alloc malloc; +func_dealloc free; + +/* return code */ +int retcode; +int tracing; + + +#define CELL_SEGSIZE 65000 /* # of cells in one segment */ +#define CELL_NSEGMENT 1000 /* # of segments for cells */ +char *alloc_seg[CELL_NSEGMENT]; +pointer cell_seg[CELL_NSEGMENT]; +int last_cell_seg; + +/* We use 4 registers. */ +pointer args; /* register for arguments of function */ +pointer envir; /* stack register for current environment */ +pointer code; /* register for current code */ +pointer dump; /* stack register for next evaluation */ + +int interactive_repl; /* are we in an interactive REPL? */ + +struct cell _sink; +pointer sink; /* when mem. alloc. fails */ +struct cell _NIL; +pointer NIL; /* special cell representing empty cell */ +struct cell _HASHT; +pointer T; /* special cell representing #t */ +struct cell _HASHF; +pointer F; /* special cell representing #f */ +struct cell _EOF_OBJ; +pointer EOF_OBJ; /* special cell representing end-of-file object */ +pointer oblist; /* pointer to symbol table */ +pointer global_env; /* pointer to global environment */ +pointer c_nest; /* stack for nested calls from C */ + +/* global pointers to special symbols */ +pointer LAMBDA; /* pointer to syntax lambda */ +pointer QUOTE; /* pointer to syntax quote */ + +pointer QQUOTE; /* pointer to symbol quasiquote */ +pointer UNQUOTE; /* pointer to symbol unquote */ +pointer UNQUOTESP; /* pointer to symbol unquote-splicing */ +pointer FEED_TO; /* => */ +pointer COLON_HOOK; /* *colon-hook* */ +pointer ERROR_HOOK; /* *error-hook* */ +pointer SHARP_HOOK; /* *sharp-hook* */ +pointer COMPILE_HOOK; /* *compile-hook* */ + +pointer free_cell; /* pointer to top of free cells */ +long fcells; /* # of free cells */ + +pointer inport; +pointer outport; +pointer save_inport; +pointer loadport; + +#define MAXFIL 64 +port load_stack[MAXFIL]; /* Stack of open files for port -1 (LOADing) */ +int nesting_stack[MAXFIL]; +int file_i; +int nesting; + +char gc_verbose; /* if gc_verbose is not zero, print gc status */ +char no_memory; /* Whether mem. alloc. has failed */ + +#define LINESIZE 1024 +char linebuff[LINESIZE]; +#define STRBUFFSIZE 256 +char strbuff[STRBUFFSIZE]; + +FILE *tmpfp; +int tok; +int print_flag; +pointer value; +int op; + +void *ext_data; /* For the benefit of foreign functions */ +long gensym_cnt; + +struct scheme_interface *vptr; +void *dump_base; /* pointer to base of allocated dump stack */ +int dump_size; /* number of frames allocated for dump stack */ +}; + +/* operator code */ +enum scheme_opcodes { +#define _OP_DEF(A,B,C,D,E,OP) OP, +#include "opdefines.h" + OP_MAXDEFINED +}; + + +#define cons(sc,a,b) _cons(sc,a,b,0) +#define immutable_cons(sc,a,b) _cons(sc,a,b,1) + +int is_string(pointer p); +char *string_value(pointer p); +int is_number(pointer p); +num nvalue(pointer p); +long ivalue(pointer p); +double rvalue(pointer p); +int is_integer(pointer p); +int is_real(pointer p); +int is_character(pointer p); +long charvalue(pointer p); +int is_vector(pointer p); + +int is_port(pointer p); + +int is_pair(pointer p); +pointer pair_car(pointer p); +pointer pair_cdr(pointer p); +pointer set_car(pointer p, pointer q); +pointer set_cdr(pointer p, pointer q); + +int is_symbol(pointer p); +char *symname(pointer p); +int hasprop(pointer p); + +int is_syntax(pointer p); +int is_proc(pointer p); +int is_foreign(pointer p); +char *syntaxname(pointer p); +int is_closure(pointer p); +#ifdef USE_MACRO +int is_macro(pointer p); +#endif +pointer closure_code(pointer p); +pointer closure_env(pointer p); + +int is_continuation(pointer p); +int is_promise(pointer p); +int is_environment(pointer p); +int is_immutable(pointer p); +void setimmutable(pointer p); + +#ifdef __cplusplus +} +#endif + +#endif + +/* +Local variables: +c-file-style: "k&r" +End: +*/ diff --git a/bootstrap/tinyscheme-1.41/scheme.c b/bootstrap/tinyscheme-1.41/scheme.c new file mode 100644 index 0000000..3b5b477 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/scheme.c @@ -0,0 +1,5143 @@ +/* T I N Y S C H E M E 1 . 4 1 + * Dimitrios Souflis (dsouflis@acm.org) + * Based on MiniScheme (original credits follow) + * (MINISCM) coded by Atsushi Moriwaki (11/5/1989) + * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp + * (MINISCM) This version has been modified by R.C. Secrist. + * (MINISCM) + * (MINISCM) Mini-Scheme is now maintained by Akira KIDA. + * (MINISCM) + * (MINISCM) This is a revised and modified version by Akira KIDA. + * (MINISCM) current version is 0.85k4 (15 May 1994) + * + */ + +#define _SCHEME_SOURCE +#include "scheme-private.h" +#ifndef WIN32 +# include +#endif +#ifdef WIN32 +#define snprintf _snprintf +#endif +#if USE_DL +# include "dynload.h" +#endif +#if USE_MATH +# include +#endif + +#include +#include +#include + +#if USE_STRCASECMP +#include +# ifndef __APPLE__ +# define stricmp strcasecmp +# endif +#endif + +#if USE_DEBUG +int debug = 0; +int debug_mark = 0; +#else +#define debug 0 +#define debug_mark 0 +#endif + +/* Used for documentation purposes, to signal functions in 'interface' */ +#define INTERFACE + +#define TOK_EOF (-1) +#define TOK_LPAREN 0 +#define TOK_RPAREN 1 +#define TOK_DOT 2 +#define TOK_ATOM 3 +#define TOK_QUOTE 4 +#define TOK_COMMENT 5 +#define TOK_DQUOTE 6 +#define TOK_BQUOTE 7 +#define TOK_COMMA 8 +#define TOK_ATMARK 9 +#define TOK_SHARP 10 +#define TOK_SHARP_CONST 11 +#define TOK_VEC 12 + +#define BACKQUOTE '`' +#define DELIMITERS "()\";\f\t\v\n\r " + +/* + * Basic memory allocation units + */ + +#define banner "TinyScheme 1.41" + +#include +#include +#include + +#ifdef __APPLE__ +static int stricmp(const char *s1, const char *s2) +{ + unsigned char c1, c2; + do { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (c1 < c2) + return -1; + else if (c1 > c2) + return 1; + s1++, s2++; + } while (c1 != 0); + return 0; +} +#endif /* __APPLE__ */ + +#if USE_STRLWR +static const char *strlwr(char *s) { + const char *p=s; + while(*s) { + *s=tolower(*s); + s++; + } + return p; +} +#endif + +#ifndef prompt +# define prompt "ts> " +#endif + +#ifndef InitFile +# define InitFile "init.scm" +#endif + +#ifndef FIRST_CELLSEGS +# define FIRST_CELLSEGS 3 +#endif + +enum scheme_types { + T_STRING=1, + T_NUMBER=2, + T_SYMBOL=3, + T_PROC=4, + T_PAIR=5, + T_CLOSURE=6, + T_CONTINUATION=7, + T_FOREIGN=8, + T_CHARACTER=9, + T_PORT=10, + T_VECTOR=11, + T_MACRO=12, + T_PROMISE=13, + T_ENVIRONMENT=14, + T_LAST_SYSTEM_TYPE=14 +}; + +/* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */ +#define ADJ 32 +#define TYPE_BITS 5 +#define T_MASKTYPE 31 /* 0000000000011111 */ +#define T_SYNTAX 4096 /* 0001000000000000 */ +#define T_IMMUTABLE 8192 /* 0010000000000000 */ +#define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */ +#define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */ +#define MARK 32768 /* 1000000000000000 */ +#define UNMARK 32767 /* 0111111111111111 */ + + +static num num_add(num a, num b); +static num num_mul(num a, num b); +static num num_div(num a, num b); +static num num_intdiv(num a, num b); +static num num_sub(num a, num b); +static num num_rem(num a, num b); +static num num_mod(num a, num b); +static int num_eq(num a, num b); +static int num_gt(num a, num b); +static int num_ge(num a, num b); +static int num_lt(num a, num b); +static int num_le(num a, num b); + +#if USE_MATH +static double round_per_R5RS(double x); +#endif +static int is_zero_double(double x); +static INLINE int num_is_integer(pointer p) { + return ((p)->_object._number.is_fixnum); +} + +static num num_zero; +static num num_one; + +/* macros for cell operations */ +#define typeflag(p) ((p)->_flag) +#define type(p) (typeflag(p)&T_MASKTYPE) + +INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); } +#define strvalue(p) ((p)->_object._string._svalue) +#define strlength(p) ((p)->_object._string._length) + +INTERFACE static int is_list(scheme *sc, pointer p); +INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); } +INTERFACE static void fill_vector(pointer vec, pointer obj); +INTERFACE static pointer vector_elem(pointer vec, int ielem); +INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a); +INTERFACE INLINE int is_number(pointer p) { return (type(p)==T_NUMBER); } +INTERFACE INLINE int is_integer(pointer p) { + if (!is_number(p)) + return 0; + if (num_is_integer(p) || (double)ivalue(p) == rvalue(p)) + return 1; + return 0; +} + +INTERFACE INLINE int is_real(pointer p) { + return is_number(p) && (!(p)->_object._number.is_fixnum); +} + +INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); } +INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); } +INLINE num nvalue(pointer p) { return ((p)->_object._number); } +INTERFACE long ivalue(pointer p) { return (num_is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); } +INTERFACE double rvalue(pointer p) { return (!num_is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); } +#define ivalue_unchecked(p) ((p)->_object._number.value.ivalue) +#define rvalue_unchecked(p) ((p)->_object._number.value.rvalue) +#define set_num_integer(p) (p)->_object._number.is_fixnum=1; +#define set_num_real(p) (p)->_object._number.is_fixnum=0; +INTERFACE long charvalue(pointer p) { return ivalue_unchecked(p); } + +INTERFACE INLINE int is_port(pointer p) { return (type(p)==T_PORT); } +INTERFACE INLINE int is_inport(pointer p) { return is_port(p) && p->_object._port->kind & port_input; } +INTERFACE INLINE int is_outport(pointer p) { return is_port(p) && p->_object._port->kind & port_output; } + +INTERFACE INLINE int is_pair(pointer p) { return (type(p)==T_PAIR); } +#define car(p) ((p)->_object._cons._car) +#define cdr(p) ((p)->_object._cons._cdr) +INTERFACE pointer pair_car(pointer p) { return car(p); } +INTERFACE pointer pair_cdr(pointer p) { return cdr(p); } +INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; } +INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; } + +INTERFACE INLINE int is_symbol(pointer p) { return (type(p)==T_SYMBOL); } +INTERFACE INLINE char *symname(pointer p) { return strvalue(car(p)); } +#if USE_PLIST +SCHEME_EXPORT INLINE int hasprop(pointer p) { return (typeflag(p)&T_SYMBOL); } +#define symprop(p) cdr(p) +#endif + +INTERFACE INLINE int is_syntax(pointer p) { return (typeflag(p)&T_SYNTAX); } +INTERFACE INLINE int is_proc(pointer p) { return (type(p)==T_PROC); } +INTERFACE INLINE int is_foreign(pointer p) { return (type(p)==T_FOREIGN); } +INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); } +#define procnum(p) ivalue(p) +static const char *procname(pointer x); + +INTERFACE INLINE int is_closure(pointer p) { return (type(p)==T_CLOSURE); } +INTERFACE INLINE int is_macro(pointer p) { return (type(p)==T_MACRO); } +INTERFACE INLINE pointer closure_code(pointer p) { return car(p); } +INTERFACE INLINE pointer closure_env(pointer p) { return cdr(p); } + +INTERFACE INLINE int is_continuation(pointer p) { return (type(p)==T_CONTINUATION); } +#define cont_dump(p) cdr(p) + +/* To do: promise should be forced ONCE only */ +INTERFACE INLINE int is_promise(pointer p) { return (type(p)==T_PROMISE); } + +INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); } +#define setenvironment(p) typeflag(p) = T_ENVIRONMENT + +#define is_atom(p) (typeflag(p)&T_ATOM) +#define setatom(p) typeflag(p) |= T_ATOM +#define clratom(p) typeflag(p) &= CLRATOM + +#define is_mark(p) (typeflag(p)&MARK) +#define setmark(p) typeflag(p) |= MARK +#define clrmark(p) typeflag(p) &= UNMARK + +INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); } +/*#define setimmutable(p) typeflag(p) |= T_IMMUTABLE*/ +INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; } + +#define caar(p) car(car(p)) +#define cadr(p) car(cdr(p)) +#define cdar(p) cdr(car(p)) +#define cddr(p) cdr(cdr(p)) +#define cadar(p) car(cdr(car(p))) +#define caddr(p) car(cdr(cdr(p))) +#define cdaar(p) cdr(car(car(p))) +#define cadaar(p) car(cdr(car(car(p)))) +#define cadddr(p) car(cdr(cdr(cdr(p)))) +#define cddddr(p) cdr(cdr(cdr(cdr(p)))) + +#if USE_CHAR_CLASSIFIERS +static INLINE int Cisalpha(int c) { return isascii(c) && isalpha(c); } +static INLINE int Cisdigit(int c) { return isascii(c) && isdigit(c); } +static INLINE int Cisspace(int c) { return isascii(c) && isspace(c); } +static INLINE int Cisupper(int c) { return isascii(c) && isupper(c); } +static INLINE int Cislower(int c) { return isascii(c) && islower(c); } +#endif + +#if USE_ASCII_NAMES +static const char *charnames[32]={ + "nul", + "soh", + "stx", + "etx", + "eot", + "enq", + "ack", + "bel", + "bs", + "ht", + "lf", + "vt", + "ff", + "cr", + "so", + "si", + "dle", + "dc1", + "dc2", + "dc3", + "dc4", + "nak", + "syn", + "etb", + "can", + "em", + "sub", + "esc", + "fs", + "gs", + "rs", + "us" +}; + +static int is_ascii_name(const char *name, int *pc) { + int i; + for(i=0; i<32; i++) { + if(stricmp(name,charnames[i])==0) { + *pc=i; + return 1; + } + } + if(stricmp(name,"del")==0) { + *pc=127; + return 1; + } + return 0; +} + +#endif + +static int file_push(scheme *sc, const char *fname); +static void file_pop(scheme *sc); +static int file_interactive(scheme *sc); +static INLINE int is_one_of(char *s, int c); +static int alloc_cellseg(scheme *sc, int n); +static long binary_decode(const char *s); +static INLINE pointer get_cell(scheme *sc, pointer a, pointer b); +static pointer _get_cell(scheme *sc, pointer a, pointer b); +static pointer reserve_cells(scheme *sc, int n); +static pointer get_consecutive_cells(scheme *sc, int n); +static pointer find_consecutive_cells(scheme *sc, int n); +static void finalize_cell(scheme *sc, pointer a); +static int count_consecutive_cells(pointer x, int needed); +static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all); +static pointer mk_number(scheme *sc, num n); +static char *store_string(scheme *sc, int len, const char *str, char fill); +static pointer mk_vector(scheme *sc, int len); +static pointer mk_atom(scheme *sc, char *q); +static pointer mk_sharp_const(scheme *sc, char *name); +static pointer mk_port(scheme *sc, port *p); +static pointer port_from_filename(scheme *sc, const char *fn, int prop); +static pointer port_from_file(scheme *sc, FILE *, int prop); +static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop); +static port *port_rep_from_filename(scheme *sc, const char *fn, int prop); +static port *port_rep_from_file(scheme *sc, FILE *, int prop); +static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop); +static void port_close(scheme *sc, pointer p, int flag); +static void mark(pointer a); +static void gc(scheme *sc, pointer a, pointer b); +static int basic_inchar(port *pt); +static int inchar(scheme *sc); +static void backchar(scheme *sc, int c); +static char *readstr_upto(scheme *sc, char *delim); +static pointer readstrexp(scheme *sc); +static INLINE int skipspace(scheme *sc); +static int token(scheme *sc); +static void printslashstring(scheme *sc, char *s, int len); +static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen); +static void printatom(scheme *sc, pointer l, int f); +static pointer mk_proc(scheme *sc, enum scheme_opcodes op); +static pointer mk_closure(scheme *sc, pointer c, pointer e); +static pointer mk_continuation(scheme *sc, pointer d); +static pointer reverse(scheme *sc, pointer a); +static pointer reverse_in_place(scheme *sc, pointer term, pointer list); +static pointer revappend(scheme *sc, pointer a, pointer b); +static void dump_stack_mark(scheme *); +static pointer opexe_0(scheme *sc, enum scheme_opcodes op); +static pointer opexe_1(scheme *sc, enum scheme_opcodes op); +static pointer opexe_2(scheme *sc, enum scheme_opcodes op); +static pointer opexe_3(scheme *sc, enum scheme_opcodes op); +static pointer opexe_4(scheme *sc, enum scheme_opcodes op); +static pointer opexe_5(scheme *sc, enum scheme_opcodes op); +static pointer opexe_6(scheme *sc, enum scheme_opcodes op); +static void Eval_Cycle(scheme *sc, enum scheme_opcodes op); +static void assign_syntax(scheme *sc, char *name); +static int syntaxnum(pointer p); +static void assign_proc(scheme *sc, enum scheme_opcodes, char *name); +long long int Eval_Cycle_Count = 0; +int Alloc_Count = 0; + +#define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue) +#define num_rvalue(n) (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue) + +static num num_add(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue+b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)+num_rvalue(b); + } + return ret; +} + +static num num_mul(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue*b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)*num_rvalue(b); + } + return ret; +} + +static num num_div(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue/b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)/num_rvalue(b); + } + return ret; +} + +static num num_intdiv(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue/b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)/num_rvalue(b); + } + return ret; +} + +static num num_sub(num a, num b) { + num ret; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + if(ret.is_fixnum) { + ret.value.ivalue= a.value.ivalue-b.value.ivalue; + } else { + ret.value.rvalue=num_rvalue(a)-num_rvalue(b); + } + return ret; +} + +static num num_rem(num a, num b) { + num ret; + long e1, e2, res; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + e1=num_ivalue(a); + e2=num_ivalue(b); + res=e1%e2; + /* remainder should have same sign as second operand */ + if (res > 0) { + if (e1 < 0) { + res -= labs(e2); + } + } else if (res < 0) { + if (e1 > 0) { + res += labs(e2); + } + } + ret.value.ivalue=res; + return ret; +} + +static num num_mod(num a, num b) { + num ret; + long e1, e2, res; + ret.is_fixnum=a.is_fixnum && b.is_fixnum; + e1=num_ivalue(a); + e2=num_ivalue(b); + res=e1%e2; + /* modulo should have same sign as second operand */ + if (res * e2 < 0) { + res += e2; + } + ret.value.ivalue=res; + return ret; +} + +static int num_eq(num a, num b) { + int ret; + int is_fixnum=a.is_fixnum && b.is_fixnum; + if(is_fixnum) { + ret= a.value.ivalue==b.value.ivalue; + } else { + ret=num_rvalue(a)==num_rvalue(b); + } + return ret; +} + + +static int num_gt(num a, num b) { + int ret; + int is_fixnum=a.is_fixnum && b.is_fixnum; + if(is_fixnum) { + ret= a.value.ivalue>b.value.ivalue; + } else { + ret=num_rvalue(a)>num_rvalue(b); + } + return ret; +} + +static int num_ge(num a, num b) { + return !num_lt(a,b); +} + +static int num_lt(num a, num b) { + int ret; + int is_fixnum=a.is_fixnum && b.is_fixnum; + if(is_fixnum) { + ret= a.value.ivaluedce) { + return ce; + } else if(dfl-DBL_MIN; +} + +static long binary_decode(const char *s) { + long x=0; + + while(*s!=0 && (*s=='1' || *s=='0')) { + x<<=1; + x+=*s-'0'; + s++; + } + + return x; +} + +/* allocate new cell segment */ +static int alloc_cellseg(scheme *sc, int n) { + pointer newp; + pointer last; + pointer p; + char *cp; + long i; + int k; + int adj=ADJ; + + if(adjlast_cell_seg >= CELL_NSEGMENT - 1) + return k; + cp = (char*) sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj); + if (cp == 0) + return k; + i = ++sc->last_cell_seg ; + sc->alloc_seg[i] = cp; + /* adjust in TYPE_BITS-bit boundary */ + if(((unsigned long)cp)%adj!=0) { + cp=(char*)(adj*((unsigned long)cp/adj+1)); + } + /* insert new segment in address order */ + newp=(pointer)cp; + sc->cell_seg[i] = newp; + while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) { + p = sc->cell_seg[i]; + sc->cell_seg[i] = sc->cell_seg[i - 1]; + sc->cell_seg[--i] = p; + } + sc->fcells += CELL_SEGSIZE; + last = newp + CELL_SEGSIZE - 1; + for (p = newp; p <= last; p++) { + typeflag(p) = 0; + cdr(p) = p + 1; + car(p) = sc->NIL; + } + /* insert new cells in address order on free list */ + if (sc->free_cell == sc->NIL || p < sc->free_cell) { + cdr(last) = sc->free_cell; + sc->free_cell = newp; + } else { + p = sc->free_cell; + while (cdr(p) != sc->NIL && newp > cdr(p)) + p = cdr(p); + cdr(last) = cdr(p); + cdr(p) = newp; + } + } + return n; +} + +static INLINE pointer get_cell_x(scheme *sc, pointer a, pointer b) { + if (sc->free_cell != sc->NIL) { + if (debug) { fprintf(stderr,"[DEBUG] get_cell_x fcells %d\n",sc->fcells); } + pointer x = sc->free_cell; + sc->free_cell = cdr(x); + --sc->fcells; + return (x); + } + if (debug) { fprintf(stderr,"[DEBUG] get_cell_x _get_cell %d\n",sc->fcells); } + return _get_cell (sc, a, b); +} + + +/* get new cell. parameter a, b is marked by gc. */ +static pointer _get_cell(scheme *sc, pointer a, pointer b) { + pointer x; + + if(sc->no_memory) { + if (debug) { fprintf(stderr,"_get_cell no_memory\n"); } + return sc->sink; + } + + if (sc->free_cell == sc->NIL) { + const int min_to_be_recovered = sc->last_cell_seg*8; + if (debug) { fprintf(stderr,"_get_cell sc->NIL\n"); } + gc(sc,a, b); + if (debug) { fprintf(stderr,"_get_cell after gc\n"); } + if (sc->fcells < min_to_be_recovered + || sc->free_cell == sc->NIL) { + /* if only a few recovered, get more to avoid fruitless gc's */ + if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) { + sc->no_memory=1; + return sc->sink; + } + } + } + x = sc->free_cell; + sc->free_cell = cdr(x); + --sc->fcells; + return (x); +} + +/* make sure that there is a given number of cells free */ +static pointer reserve_cells(scheme *sc, int n) { + if(sc->no_memory) { + return sc->NIL; + } + + /* Are there enough cells available? */ + if (sc->fcells < n) { + /* If not, try gc'ing some */ + gc(sc, sc->NIL, sc->NIL); + if (sc->fcells < n) { + /* If there still aren't, try getting more heap */ + if (!alloc_cellseg(sc,1)) { + sc->no_memory=1; + return sc->NIL; + } + } + if (sc->fcells < n) { + /* If all fail, report failure */ + sc->no_memory=1; + return sc->NIL; + } + } + return (sc->T); +} + +static pointer get_consecutive_cells(scheme *sc, int n) { + pointer x; + + if(sc->no_memory) { return sc->sink; } + + /* Are there any cells available? */ + x=find_consecutive_cells(sc,n); + if (x != sc->NIL) { return x; } + + /* If not, try gc'ing some */ + gc(sc, sc->NIL, sc->NIL); + x=find_consecutive_cells(sc,n); + if (x != sc->NIL) { return x; } + + /* If there still aren't, try getting more heap */ + if (!alloc_cellseg(sc,1)) + { + sc->no_memory=1; + return sc->sink; + } + + x=find_consecutive_cells(sc,n); + if (x != sc->NIL) { return x; } + + /* If all fail, report failure */ + sc->no_memory=1; + return sc->sink; +} + +static int count_consecutive_cells(pointer x, int needed) { + int n=1; + while(cdr(x)==x+1) { + x=cdr(x); + n++; + if(n>needed) return n; + } + return n; +} + +static pointer find_consecutive_cells(scheme *sc, int n) { + pointer *pp; + int cnt; + + pp=&sc->free_cell; + while(*pp!=sc->NIL) { + cnt=count_consecutive_cells(*pp,n); + if(cnt>=n) { + pointer x=*pp; + *pp=cdr(*pp+n-1); + sc->fcells -= n; + return x; + } + pp=&cdr(*pp+cnt-1); + } + return sc->NIL; +} + +/* To retain recent allocs before interpreter knows about them - + Tehom */ + +static void push_recent_alloc(scheme *sc, pointer recent, pointer extra) +{ + if (debug) { fprintf(stderr,"[DEBUG] push_recent_alloc get_cell_x\n"); } + pointer holder = get_cell_x(sc, recent, extra); + if (debug) { fprintf(stderr,"[DEBUG] push_recent_alloc set typeflag\n"); } + typeflag(holder) = T_PAIR | T_IMMUTABLE; + if (debug) { fprintf(stderr,"[DEBUG] push_recent_alloc set contents\n"); } + car(holder) = recent; + cdr(holder) = car(sc->sink); + if (debug) { fprintf(stderr,"[DEBUG] push_recent_alloc set sink\n"); } + car(sc->sink) = holder; + if (debug) { fprintf(stderr,"[DEBUG] push_recent_alloc set sink complete\n"); } +} + + +static pointer get_cell(scheme *sc, pointer a, pointer b) +{ + pointer cell; + if (debug) { fprintf(stderr,"[DEBUG] get_cell_x\n"); } + cell = get_cell_x(sc, a, b); + /* For right now, include "a" and "b" in "cell" so that gc doesn't + think they are garbage. */ + /* Tentatively record it as a pair so gc understands it. */ + if (debug) { fprintf(stderr,"[DEBUG] set_flag\n"); } + typeflag(cell) = T_PAIR; + if (debug) { fprintf(stderr,"[DEBUG] set contents\n"); } + car(cell) = a; + cdr(cell) = b; + if (debug) { fprintf(stderr,"[DEBUG] push_recent_alloc\n"); } + push_recent_alloc(sc, cell, sc->NIL); + if (debug) { fprintf(stderr,"[DEBUG] push_recent_alloc complete\n"); } + return cell; +} + +static pointer get_vector_object(scheme *sc, int len, pointer init) +{ + pointer cells = get_consecutive_cells(sc,len/2+len%2+1); + if(sc->no_memory) { return sc->sink; } + /* Record it as a vector so that gc understands it. */ + typeflag(cells) = (T_VECTOR | T_ATOM); + ivalue_unchecked(cells)=len; + set_num_integer(cells); + fill_vector(cells,init); + push_recent_alloc(sc, cells, sc->NIL); + return cells; +} + +static INLINE void ok_to_freely_gc(scheme *sc) +{ + car(sc->sink) = sc->NIL; +} + + +#if defined TSGRIND +static void check_cell_alloced(pointer p, int expect_alloced) +{ + /* Can't use putstr(sc,str) because callers have no access to + sc. */ + if(typeflag(p) & !expect_alloced) + { + fprintf(stderr,"Cell is already allocated!\n"); + } + if(!(typeflag(p)) & expect_alloced) + { + fprintf(stderr,"Cell is not allocated!\n"); + } + +} +static void check_range_alloced(pointer p, int n, int expect_alloced) +{ + int i; + for(i = 0;iNIL); + typeflag(x) = T_SYMBOL; + setimmutable(car(x)); + + location = hash_fn(name, ivalue_unchecked(sc->oblist)); + set_vector_elem(sc->oblist, location, + immutable_cons(sc, x, vector_elem(sc->oblist, location))); + return x; +} + +static INLINE pointer oblist_find_by_name(scheme *sc, const char *name) +{ + int location; + pointer x; + char *s; + + location = hash_fn(name, ivalue_unchecked(sc->oblist)); + for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) { + s = symname(car(x)); + /* case-insensitive, per R5RS section 2. */ + if(stricmp(name, s) == 0) { + return car(x); + } + } + return sc->NIL; +} + +static pointer oblist_all_symbols(scheme *sc) +{ + int i; + pointer x; + pointer ob_list = sc->NIL; + + for (i = 0; i < ivalue_unchecked(sc->oblist); i++) { + for (x = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) { + ob_list = cons(sc, x, ob_list); + } + } + return ob_list; +} + +#else + +static pointer oblist_initial_value(scheme *sc) +{ + return sc->NIL; +} + +static INLINE pointer oblist_find_by_name(scheme *sc, const char *name) +{ + pointer x; + char *s; + + for (x = sc->oblist; x != sc->NIL; x = cdr(x)) { + s = symname(car(x)); + /* case-insensitive, per R5RS section 2. */ + if(stricmp(name, s) == 0) { + return car(x); + } + } + return sc->NIL; +} + +/* returns the new symbol */ +static pointer oblist_add_by_name(scheme *sc, const char *name) +{ + pointer x; + + x = immutable_cons(sc, mk_string(sc, name), sc->NIL); + typeflag(x) = T_SYMBOL; + setimmutable(car(x)); + sc->oblist = immutable_cons(sc, x, sc->oblist); + return x; +} +static pointer oblist_all_symbols(scheme *sc) +{ + return sc->oblist; +} + +#endif + +static pointer mk_port(scheme *sc, port *p) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + + typeflag(x) = T_PORT|T_ATOM; + x->_object._port=p; + return (x); +} + +pointer mk_foreign_func(scheme *sc, foreign_func f) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + + typeflag(x) = (T_FOREIGN | T_ATOM); + x->_object._ff=f; + return (x); +} + +INTERFACE pointer mk_character(scheme *sc, int c) { + pointer x = get_cell(sc,sc->NIL, sc->NIL); + + typeflag(x) = (T_CHARACTER | T_ATOM); + ivalue_unchecked(x)= c; + set_num_integer(x); + return (x); +} + +/* get number atom (integer) */ +INTERFACE pointer mk_integer(scheme *sc, long num) { + pointer x = get_cell(sc,sc->NIL, sc->NIL); + + typeflag(x) = (T_NUMBER | T_ATOM); + ivalue_unchecked(x)= num; + set_num_integer(x); + return (x); +} + +INTERFACE pointer mk_real(scheme *sc, double n) { + pointer x = get_cell(sc,sc->NIL, sc->NIL); + + typeflag(x) = (T_NUMBER | T_ATOM); + rvalue_unchecked(x)= n; + set_num_real(x); + return (x); +} + +static pointer mk_number(scheme *sc, num n) { + if(n.is_fixnum) { + return mk_integer(sc,n.value.ivalue); + } else { + return mk_real(sc,n.value.rvalue); + } +} + +/* allocate name to string area */ +static char *store_string(scheme *sc, int len_str, const char *str, char fill) { + char *q; + + q=(char*)sc->malloc(len_str+1); + if(q==0) { + sc->no_memory=1; + return sc->strbuff; + } + if(str!=0) { + snprintf(q, len_str+1, "%s", str); + } else { + memset(q, fill, len_str); + q[len_str]=0; + } + return (q); +} + +/* get new string */ +INTERFACE pointer mk_string(scheme *sc, const char *str) { + return mk_counted_string(sc,str,strlen(str)); +} + +INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + typeflag(x) = (T_STRING | T_ATOM); + strvalue(x) = store_string(sc,len,str,0); + strlength(x) = len; + return (x); +} + +INTERFACE pointer mk_empty_string(scheme *sc, int len, char fill) { + pointer x = get_cell(sc, sc->NIL, sc->NIL); + typeflag(x) = (T_STRING | T_ATOM); + strvalue(x) = store_string(sc,len,0,fill); + strlength(x) = len; + return (x); +} + +INTERFACE static pointer mk_vector(scheme *sc, int len) +{ return get_vector_object(sc,len,sc->NIL); } + +INTERFACE static void fill_vector(pointer vec, pointer obj) { + int i; + int num=ivalue(vec)/2+ivalue(vec)%2; + for(i=0; iNIL) { + return (x); + } else { + x = oblist_add_by_name(sc, name); + return (x); + } +} + +INTERFACE pointer gensym(scheme *sc) { + pointer x; + char name[40]; + + for(; sc->gensym_cntgensym_cnt++) { + snprintf(name,40,"gensym-%ld",sc->gensym_cnt); + + /* first check oblist */ + x = oblist_find_by_name(sc, name); + + if (x != sc->NIL) { + continue; + } else { + x = oblist_add_by_name(sc, name); + return (x); + } + } + + return sc->NIL; +} + +/* make symbol or number atom from string */ +static pointer mk_atom(scheme *sc, char *q) { + char c, *p; + int has_dec_point=0; + int has_fp_exp = 0; + +#if USE_COLON_HOOK + if((p=strstr(q,"::"))!=0) { + *p=0; + return cons(sc, sc->COLON_HOOK, + cons(sc, + cons(sc, + sc->QUOTE, + cons(sc, mk_atom(sc,p+2), sc->NIL)), + cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL))); + } +#endif + + p = q; + c = *p++; + if ((c == '+') || (c == '-')) { + c = *p++; + if (c == '.') { + has_dec_point=1; + c = *p++; + } + if (!isdigit(c)) { + return (mk_symbol(sc, strlwr(q))); + } + } else if (c == '.') { + has_dec_point=1; + c = *p++; + if (!isdigit(c)) { + return (mk_symbol(sc, strlwr(q))); + } + } else if (!isdigit(c)) { + return (mk_symbol(sc, strlwr(q))); + } + + for ( ; (c = *p) != 0; ++p) { + if (!isdigit(c)) { + if(c=='.') { + if(!has_dec_point) { + has_dec_point=1; + continue; + } + } + else if ((c == 'e') || (c == 'E')) { + if(!has_fp_exp) { + has_dec_point = 1; /* decimal point illegal + from now on */ + p++; + if ((*p == '-') || (*p == '+') || isdigit(*p)) { + continue; + } + } + } + return (mk_symbol(sc, strlwr(q))); + } + } + if(has_dec_point) { + return mk_real(sc,atof(q)); + } + return (mk_integer(sc, atol(q))); +} + +/* make constant */ +static pointer mk_sharp_const(scheme *sc, char *name) { + long x; + char tmp[STRBUFFSIZE]; + + if (!strcmp(name, "t")) + return (sc->T); + else if (!strcmp(name, "f")) + return (sc->F); + else if (*name == 'o') {/* #o (octal) */ + snprintf(tmp, STRBUFFSIZE, "0%s", name+1); + sscanf(tmp, "%lo", (long unsigned *)&x); + return (mk_integer(sc, x)); + } else if (*name == 'd') { /* #d (decimal) */ + sscanf(name+1, "%ld", (long int *)&x); + return (mk_integer(sc, x)); + } else if (*name == 'x') { /* #x (hex) */ + snprintf(tmp, STRBUFFSIZE, "0x%s", name+1); + sscanf(tmp, "%lx", (long unsigned *)&x); + return (mk_integer(sc, x)); + } else if (*name == 'b') { /* #b (binary) */ + x = binary_decode(name+1); + return (mk_integer(sc, x)); + } else if (*name == '\\') { /* #\w (character) */ + int c=0; + if(stricmp(name+1,"space")==0) { + c=' '; + } else if(stricmp(name+1,"newline")==0) { + c='\n'; + } else if(stricmp(name+1,"return")==0) { + c='\r'; + } else if(stricmp(name+1,"tab")==0) { + c='\t'; + } else if(name[1]=='x' && name[2]!=0) { + int c1=0; + if(sscanf(name+2,"%x",(unsigned int *)&c1)==1 && c1 < UCHAR_MAX) { + c=c1; + } else { + return sc->NIL; + } +#if USE_ASCII_NAMES + } else if(is_ascii_name(name+1,&c)) { + /* nothing */ +#endif + } else if(name[2]==0) { + c=name[1]; + } else { + return sc->NIL; + } + return mk_character(sc,c); + } else + return (sc->NIL); +} + +/* ========== garbage collector ========== */ + +/*-- + * We use algorithm E (Knuth, The Art of Computer Programming Vol.1, + * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm, + * for marking. + */ +static void mark(pointer a) { + static pointer badpointer = (pointer)0x0063F380; + int extra_debug = 0; + pointer t, q, p; + + t = (pointer) 0; + p = a; +E2: + if (debug_mark) { fprintf(stderr,"[DEBUG] mark(%p)\n",(void*)p); } + if (debug_mark) { fprintf(stderr,"[DEBUG] mark type = %d\n",typeflag(p)); } + /* extra_debug = debug_mark && (badpointer == p); */ + if (debug_mark) { fprintf(stderr,"[DEBUG] badpointer=%d\n",extra_debug); } + setmark(p); + if(is_vector(p)) { + if (extra_debug) { fprintf(stderr,"[DEBUG] mark is_vector\n"); } + int i; + int num=ivalue_unchecked(p)/2+ivalue_unchecked(p)%2; + for(i=0; ilast_cell_seg < CELL_NSEGMENT-1) { + return; + } + + if(sc->gc_verbose) { + putstr(sc, "gc..."); + } + + if (debug) { fprintf(stderr,"[DEBUG] mark globals, registers\n"); } + /* mark system globals */ + mark(sc->oblist); + mark(sc->global_env); + + if (debug) { fprintf(stderr,"[DEBUG] mark registers\n"); } + /* mark current registers */ + mark(sc->args); + if (debug) { fprintf(stderr,"[DEBUG] sc->NIL [%p]\n", (void*)sc->NIL); } + if (debug) { fprintf(stderr,"[DEBUG] sc->EOF_OBJ [%p]\n", (void*)sc->EOF_OBJ); } + if (debug) { fprintf(stderr,"[DEBUG] mark envir [%p]\n", (void*)sc->envir); } + if (debug) { fprintf(stderr,"[DEBUG] mark envir type [%d]\n", typeflag(sc->envir)); } + /* if (debug) { debug_mark = 1; } */ + mark(sc->envir); + if (debug) { fprintf(stderr,"[DEBUG] mark code\n"); } + mark(sc->code); + if (debug) { fprintf(stderr,"[DEBUG] dump_stack_mark\n"); } + dump_stack_mark(sc); + mark(sc->value); + mark(sc->inport); + mark(sc->save_inport); + mark(sc->outport); + mark(sc->loadport); + + if (debug) { fprintf(stderr,"[DEBUG] mark sink\n"); } + /* Mark recent objects the interpreter doesn't know about yet. */ + mark(car(sc->sink)); + /* Mark any older stuff above nested C calls */ + mark(sc->c_nest); + + /* mark variables a, b */ + mark(a); + mark(b); + + if (debug) { fprintf(stderr,"[DEBUG] sweep\n"); } + /* garbage collect */ + clrmark(sc->NIL); + sc->fcells = 0; + sc->free_cell = sc->NIL; + /* free-list is kept sorted by address so as to maintain consecutive + ranges, if possible, for use with vectors. Here we scan the cells + (which are also kept sorted by address) downwards to build the + free-list in sorted order. + */ + for (i = sc->last_cell_seg; i >= 0; i--) { + p = sc->cell_seg[i] + CELL_SEGSIZE; + while (--p >= sc->cell_seg[i]) { + if (is_mark(p)) { + clrmark(p); + } else { + /* reclaim cell */ + if (typeflag(p) != 0) { + finalize_cell(sc, p); + typeflag(p) = 0; + car(p) = sc->NIL; + } + ++sc->fcells; + cdr(p) = sc->free_cell; + sc->free_cell = p; + } + } + } + + if (sc->gc_verbose) { + char msg[80]; + snprintf(msg,80,"done: %ld cells were recovered.\n", sc->fcells); + putstr(sc,msg); + } + + if(++gc_count%1000==0||sc->fcells>500000) { + fprintf(stdout,";; fcells=%ld gc_count=%d Eval_Cycle_Count=%lld\n", sc->fcells, gc_count, Eval_Cycle_Count); + } +} + +static void finalize_cell(scheme *sc, pointer a) { + if(is_string(a)) { + sc->free(strvalue(a)); + } else if(is_port(a)) { + if(a->_object._port->kind&port_file + && a->_object._port->rep.stdio.closeit) { + port_close(sc,a,port_input|port_output); + } + sc->free(a->_object._port); + } +} + +/* ========== Routines for Reading ========== */ + +static int file_push(scheme *sc, const char *fname) { + FILE *fin = NULL; + + if (sc->file_i == MAXFIL-1) + return 0; + fin=fopen(fname,"r"); + if(fin!=0) { + sc->file_i++; + sc->load_stack[sc->file_i].kind=port_file|port_input; + sc->load_stack[sc->file_i].rep.stdio.file=fin; + sc->load_stack[sc->file_i].rep.stdio.closeit=1; + sc->nesting_stack[sc->file_i]=0; + sc->loadport->_object._port=sc->load_stack+sc->file_i; + +#if SHOW_ERROR_LINE + sc->load_stack[sc->file_i].rep.stdio.curr_line = 0; + if(fname) + sc->load_stack[sc->file_i].rep.stdio.filename = store_string(sc, strlen(fname), fname, 0); +#endif + } + return fin!=0; +} + +static void file_pop(scheme *sc) { + if(sc->file_i != 0) { + sc->nesting=sc->nesting_stack[sc->file_i]; + port_close(sc,sc->loadport,port_input); + sc->file_i--; + sc->loadport->_object._port=sc->load_stack+sc->file_i; + } +} + +static int file_interactive(scheme *sc) { + return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin + && sc->inport->_object._port->kind&port_file; +} + +static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) { + FILE *f; + char *rw; + port *pt; + if(prop==(port_input|port_output)) { + rw="a+"; + } else if(prop==port_output) { + rw="w"; + } else { + rw="r"; + } + f=fopen(fn,rw); + if(f==0) { + return 0; + } + pt=port_rep_from_file(sc,f,prop); + pt->rep.stdio.closeit=1; + +#if SHOW_ERROR_LINE + if(fn) + pt->rep.stdio.filename = store_string(sc, strlen(fn), fn, 0); + + pt->rep.stdio.curr_line = 0; +#endif + return pt; +} + +static pointer port_from_filename(scheme *sc, const char *fn, int prop) { + port *pt; + pt=port_rep_from_filename(sc,fn,prop); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +static port *port_rep_from_file(scheme *sc, FILE *f, int prop) +{ + port *pt; + + pt = (port *)sc->malloc(sizeof *pt); + if (pt == NULL) { + return NULL; + } + pt->kind = port_file | prop; + pt->rep.stdio.file = f; + pt->rep.stdio.closeit = 0; + return pt; +} + +static pointer port_from_file(scheme *sc, FILE *f, int prop) { + port *pt; + pt=port_rep_from_file(sc,f,prop); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) { + port *pt; + pt=(port*)sc->malloc(sizeof(port)); + if(pt==0) { + return 0; + } + pt->kind=port_string|prop; + pt->rep.string.start=start; + pt->rep.string.curr=start; + pt->rep.string.past_the_end=past_the_end; + return pt; +} + +static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) { + port *pt; + pt=port_rep_from_string(sc,start,past_the_end,prop); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +#define BLOCK_SIZE 256 + +static port *port_rep_from_scratch(scheme *sc) { + port *pt; + char *start; + pt=(port*)sc->malloc(sizeof(port)); + if(pt==0) { + return 0; + } + start=sc->malloc(BLOCK_SIZE); + if(start==0) { + return 0; + } + memset(start,' ',BLOCK_SIZE-1); + start[BLOCK_SIZE-1]='\0'; + pt->kind=port_string|port_output|port_srfi6; + pt->rep.string.start=start; + pt->rep.string.curr=start; + pt->rep.string.past_the_end=start+BLOCK_SIZE-1; + return pt; +} + +static pointer port_from_scratch(scheme *sc) { + port *pt; + pt=port_rep_from_scratch(sc); + if(pt==0) { + return sc->NIL; + } + return mk_port(sc,pt); +} + +static void port_close(scheme *sc, pointer p, int flag) { + port *pt=p->_object._port; + pt->kind&=~flag; + if((pt->kind & (port_input|port_output))==0) { + if(pt->kind&port_file) { + +#if SHOW_ERROR_LINE + /* Cleanup is here so (close-*-port) functions could work too */ + pt->rep.stdio.curr_line = 0; + + if(pt->rep.stdio.filename) + sc->free(pt->rep.stdio.filename); +#endif + + fclose(pt->rep.stdio.file); + } + pt->kind=port_free; + } +} + +/* get new character from input file */ +static int inchar(scheme *sc) { + int c; + port *pt; + + pt = sc->inport->_object._port; + if(pt->kind & port_saw_EOF) + { return EOF; } + c = basic_inchar(pt); + if(c == EOF && sc->inport == sc->loadport) { + /* Instead, set port_saw_EOF */ + pt->kind |= port_saw_EOF; + + /* file_pop(sc); */ + return EOF; + /* NOTREACHED */ + } + return c; +} + +static int basic_inchar(port *pt) { + if(pt->kind & port_file) { + return fgetc(pt->rep.stdio.file); + } else { + if(*pt->rep.string.curr == 0 || + pt->rep.string.curr == pt->rep.string.past_the_end) { + return EOF; + } else { + return *pt->rep.string.curr++; + } + } +} + +/* back character to input buffer */ +static void backchar(scheme *sc, int c) { + port *pt; + if(c==EOF) return; + pt=sc->inport->_object._port; + if(pt->kind&port_file) { + ungetc(c,pt->rep.stdio.file); + } else { + if(pt->rep.string.curr!=pt->rep.string.start) { + --pt->rep.string.curr; + } + } +} + +static int realloc_port_string(scheme *sc, port *p) +{ + char *start=p->rep.string.start; + size_t new_size=p->rep.string.past_the_end-start+1+BLOCK_SIZE; + char *str=sc->malloc(new_size); + if(str) { + memset(str,' ',new_size-1); + str[new_size-1]='\0'; + strcpy(str,start); + p->rep.string.start=str; + p->rep.string.past_the_end=str+new_size-1; + p->rep.string.curr-=start-str; + sc->free(start); + return 1; + } else { + return 0; + } +} + +INTERFACE void putstr(scheme *sc, const char *s) { + port *pt=sc->outport->_object._port; + if(pt->kind&port_file) { + fputs(s,pt->rep.stdio.file); + } else { + for(;*s;s++) { + if(pt->rep.string.curr!=pt->rep.string.past_the_end) { + *pt->rep.string.curr++=*s; + } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) { + *pt->rep.string.curr++=*s; + } + } + } +} + +static void putchars(scheme *sc, const char *s, int len) { + port *pt=sc->outport->_object._port; + if(pt->kind&port_file) { + fwrite(s,1,len,pt->rep.stdio.file); + } else { + for(;len;len--) { + if(pt->rep.string.curr!=pt->rep.string.past_the_end) { + *pt->rep.string.curr++=*s++; + } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) { + *pt->rep.string.curr++=*s++; + } + } + } +} + +INTERFACE void putcharacter(scheme *sc, int c) { + port *pt=sc->outport->_object._port; + if(pt->kind&port_file) { + fputc(c,pt->rep.stdio.file); + } else { + if(pt->rep.string.curr!=pt->rep.string.past_the_end) { + *pt->rep.string.curr++=c; + } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) { + *pt->rep.string.curr++=c; + } + } +} + +/* read characters up to delimiter, but cater to character constants */ +static char *readstr_upto(scheme *sc, char *delim) { + char *p = sc->strbuff; + + while ((p - sc->strbuff < sizeof(sc->strbuff)) && + !is_one_of(delim, (*p++ = inchar(sc)))); + + if(p == sc->strbuff+2 && p[-2] == '\\') { + *p=0; + } else { + backchar(sc,p[-1]); + *--p = '\0'; + } + return sc->strbuff; +} + +/* read string expression "xxx...xxx" */ +static pointer readstrexp(scheme *sc) { + char *p = sc->strbuff; + int c; + int c1=0; + enum { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2 } state=st_ok; + + for (;;) { + c=inchar(sc); + if(c == EOF || p-sc->strbuff > sizeof(sc->strbuff)-1) { + return sc->F; + } + switch(state) { + case st_ok: + switch(c) { + case '\\': + state=st_bsl; + break; + case '"': + *p=0; + return mk_counted_string(sc,sc->strbuff,p-sc->strbuff); + default: + *p++=c; + break; + } + break; + case st_bsl: + switch(c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + state=st_oct1; + c1=c-'0'; + break; + case 'x': + case 'X': + state=st_x1; + c1=0; + break; + case 'n': + *p++='\n'; + state=st_ok; + break; + case 't': + *p++='\t'; + state=st_ok; + break; + case 'r': + *p++='\r'; + state=st_ok; + break; + case '"': + *p++='"'; + state=st_ok; + break; + default: + *p++=c; + state=st_ok; + break; + } + break; + case st_x1: + case st_x2: + c=toupper(c); + if(c>='0' && c<='F') { + if(c<='9') { + c1=(c1<<4)+c-'0'; + } else { + c1=(c1<<4)+c-'A'+10; + } + if(state==st_x1) { + state=st_x2; + } else { + *p++=c1; + state=st_ok; + } + } else { + return sc->F; + } + break; + case st_oct1: + case st_oct2: + if (c < '0' || c > '7') + { + *p++=c1; + backchar(sc, c); + state=st_ok; + } + else + { + if (state==st_oct2 && c1 >= 32) + return sc->F; + + c1=(c1<<3)+(c-'0'); + + if (state == st_oct1) + state=st_oct2; + else + { + *p++=c1; + state=st_ok; + } + } + break; + + } + } +} + +/* check c is in chars */ +static INLINE int is_one_of(char *s, int c) { + if(c==EOF) return 1; + while (*s) + if (*s++ == c) + return (1); + return (0); +} + +/* skip white characters */ +static INLINE int skipspace(scheme *sc) { + int c = 0, curr_line = 0; + + do { + c=inchar(sc); +#if SHOW_ERROR_LINE + if(c=='\n') + curr_line++; +#endif + } while (isspace(c)); + +/* record it */ +#if SHOW_ERROR_LINE + if (sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line += curr_line; +#endif + + if(c!=EOF) { + backchar(sc,c); + return 1; + } + else + { return EOF; } +} + +/* get token */ +static int token(scheme *sc) { + int c; + c = skipspace(sc); + if(c == EOF) { return (TOK_EOF); } + switch (c=inchar(sc)) { + case EOF: + return (TOK_EOF); + case '(': + return (TOK_LPAREN); + case ')': + return (TOK_RPAREN); + case '.': + c=inchar(sc); + if(is_one_of(" \n\t",c)) { + return (TOK_DOT); + } else { + backchar(sc,c); + backchar(sc,'.'); + return TOK_ATOM; + } + case '\'': + return (TOK_QUOTE); + case ';': + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + +#if SHOW_ERROR_LINE + if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line++; +#endif + + if(c == EOF) + { return (TOK_EOF); } + else + { return (token(sc));} + case '"': + return (TOK_DQUOTE); + case BACKQUOTE: + return (TOK_BQUOTE); + case ',': + if ((c=inchar(sc)) == '@') { + return (TOK_ATMARK); + } else { + backchar(sc,c); + return (TOK_COMMA); + } + case '#': + c=inchar(sc); + if (c == '(') { + return (TOK_VEC); + } else if(c == '!') { + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + +#if SHOW_ERROR_LINE + if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line++; +#endif + + if(c == EOF) + { return (TOK_EOF); } + else + { return (token(sc));} + } else { + backchar(sc,c); + if(is_one_of(" tfodxb\\",c)) { + return TOK_SHARP_CONST; + } else { + return (TOK_SHARP); + } + } + default: + backchar(sc,c); + return (TOK_ATOM); + } +} + +/* ========== Routines for Printing ========== */ +#define ok_abbrev(x) (is_pair(x) && cdr(x) == sc->NIL) + +static void printslashstring(scheme *sc, char *p, int len) { + int i; + unsigned char *s=(unsigned char*)p; + putcharacter(sc,'"'); + for ( i=0; iNIL) { + p = "()"; + } else if (l == sc->T) { + p = "#t"; + } else if (l == sc->F) { + p = "#f"; + } else if (l == sc->EOF_OBJ) { + p = "#"; + } else if (is_port(l)) { + p = sc->strbuff; + snprintf(p, STRBUFFSIZE, "#"); + } else if (is_number(l)) { + p = sc->strbuff; + if (f <= 1 || f == 10) /* f is the base for numbers if > 1 */ { + if(num_is_integer(l)) { + snprintf(p, STRBUFFSIZE, "%ld", ivalue_unchecked(l)); + } else { + snprintf(p, STRBUFFSIZE, "%.10g", rvalue_unchecked(l)); + /* r5rs says there must be a '.' (unless 'e'?) */ + f = strcspn(p, ".e"); + if (p[f] == 0) { + p[f] = '.'; /* not found, so add '.0' at the end */ + p[f+1] = '0'; + p[f+2] = 0; + } + } + } else { + long v = ivalue(l); + if (f == 16) { + if (v >= 0) + snprintf(p, STRBUFFSIZE, "%lx", v); + else + snprintf(p, STRBUFFSIZE, "-%lx", -v); + } else if (f == 8) { + if (v >= 0) + snprintf(p, STRBUFFSIZE, "%lo", v); + else + snprintf(p, STRBUFFSIZE, "-%lo", -v); + } else if (f == 2) { + unsigned long b = (v < 0) ? -v : v; + p = &p[STRBUFFSIZE-1]; + *p = 0; + do { *--p = (b&1) ? '1' : '0'; b >>= 1; } while (b != 0); + if (v < 0) *--p = '-'; + } + } + } else if (is_string(l)) { + if (!f) { + p = strvalue(l); + } else { /* Hack, uses the fact that printing is needed */ + *pp=sc->strbuff; + *plen=0; + printslashstring(sc, strvalue(l), strlength(l)); + return; + } + } else if (is_character(l)) { + int c=charvalue(l); + p = sc->strbuff; + if (!f) { + p[0]=c; + p[1]=0; + } else { + switch(c) { + case ' ': + snprintf(p,STRBUFFSIZE,"#\\space"); break; + case '\n': + snprintf(p,STRBUFFSIZE,"#\\newline"); break; + case '\r': + snprintf(p,STRBUFFSIZE,"#\\return"); break; + case '\t': + snprintf(p,STRBUFFSIZE,"#\\tab"); break; + default: +#if USE_ASCII_NAMES + if(c==127) { + snprintf(p,STRBUFFSIZE, "#\\del"); + break; + } else if(c<32) { + snprintf(p, STRBUFFSIZE, "#\\%s", charnames[c]); + break; + } +#else + if(c<32) { + snprintf(p,STRBUFFSIZE,"#\\x%x",c); break; + break; + } +#endif + snprintf(p,STRBUFFSIZE,"#\\%c",c); break; + break; + } + } + } else if (is_symbol(l)) { + p = symname(l); + } else if (is_proc(l)) { + p = sc->strbuff; + snprintf(p,STRBUFFSIZE,"#<%s PROCEDURE %ld>", procname(l),procnum(l)); + } else if (is_macro(l)) { + p = "#"; + } else if (is_closure(l)) { + p = "#"; + } else if (is_promise(l)) { + p = "#"; + } else if (is_foreign(l)) { + p = sc->strbuff; + snprintf(p,STRBUFFSIZE,"#", procnum(l)); + } else if (is_continuation(l)) { + p = "#"; + } else { + p = "#"; + } + *pp=p; + *plen=strlen(p); +} +/* ========== Routines for Evaluation Cycle ========== */ + +/* make closure. c is code. e is environment */ +static pointer mk_closure(scheme *sc, pointer c, pointer e) { + pointer x = get_cell(sc, c, e); + + typeflag(x) = T_CLOSURE; + car(x) = c; + cdr(x) = e; + return (x); +} + +/* make continuation. */ +static pointer mk_continuation(scheme *sc, pointer d) { + pointer x = get_cell(sc, sc->NIL, d); + + typeflag(x) = T_CONTINUATION; + cont_dump(x) = d; + return (x); +} + +static pointer list_star(scheme *sc, pointer d) { + pointer p, q; + if(cdr(d)==sc->NIL) { + return car(d); + } + p=cons(sc,car(d),cdr(d)); + q=p; + while(cdr(cdr(p))!=sc->NIL) { + d=cons(sc,car(p),cdr(p)); + if(cdr(cdr(p))!=sc->NIL) { + p=cdr(d); + } + } + cdr(p)=car(cdr(p)); + return q; +} + +/* reverse list -- produce new list */ +static pointer reverse(scheme *sc, pointer a) { +/* a must be checked by gc */ + pointer p = sc->NIL; + + for ( ; is_pair(a); a = cdr(a)) { + p = cons(sc, car(a), p); + } + return (p); +} + +/* reverse list --- in-place */ +static pointer reverse_in_place(scheme *sc, pointer term, pointer list) { + pointer p = list, result = term, q; + + while (p != sc->NIL) { + q = cdr(p); + cdr(p) = result; + result = p; + p = q; + } + return (result); +} + +/* append list -- produce new list (in reverse order) */ +static pointer revappend(scheme *sc, pointer a, pointer b) { + pointer result = a; + pointer p = b; + + while (is_pair(p)) { + result = cons(sc, car(p), result); + p = cdr(p); + } + + if (p == sc->NIL) { + return result; + } + + return sc->F; /* signal an error */ +} + +/* equivalence of atoms */ +int eqv(pointer a, pointer b) { + if (is_string(a)) { + if (is_string(b)) + return (strvalue(a) == strvalue(b)); + else + return (0); + } else if (is_number(a)) { + if (is_number(b)) { + if (num_is_integer(a) == num_is_integer(b)) + return num_eq(nvalue(a),nvalue(b)); + } + return (0); + } else if (is_character(a)) { + if (is_character(b)) + return charvalue(a)==charvalue(b); + else + return (0); + } else if (is_port(a)) { + if (is_port(b)) + return a==b; + else + return (0); + } else if (is_proc(a)) { + if (is_proc(b)) + return procnum(a)==procnum(b); + else + return (0); + } else { + return (a == b); + } +} + +/* true or false value macro */ +/* () is #t in R5RS */ +#define is_true(p) ((p) != sc->F) +#define is_false(p) ((p) == sc->F) + +/* ========== Environment implementation ========== */ + +#if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST) + +static int hash_fn(const char *key, int table_size) +{ + unsigned int hashed = 0; + const char *c; + int bits_per_int = sizeof(unsigned int)*8; + + for (c = key; *c; c++) { + /* letters have about 5 bits in them */ + hashed = (hashed<<5) | (hashed>>(bits_per_int-5)); + hashed ^= *c; + } + return hashed % table_size; +} +#endif + +#ifndef USE_ALIST_ENV + +/* + * In this implementation, each frame of the environment may be + * a hash table: a vector of alists hashed by variable name. + * In practice, we use a vector only for the initial frame; + * subsequent frames are too small and transient for the lookup + * speed to out-weigh the cost of making a new vector. + */ + +static void new_frame_in_env(scheme *sc, pointer old_env) +{ + pointer new_frame; + + /* The interaction-environment has about 300 variables in it. */ + if (old_env == sc->NIL) { + new_frame = mk_vector(sc, 461); + } else { + new_frame = sc->NIL; + } + + sc->envir = immutable_cons(sc, new_frame, old_env); + setenvironment(sc->envir); +} + +static INLINE void new_slot_spec_in_env(scheme *sc, pointer env, + pointer variable, pointer value) +{ + pointer slot = immutable_cons(sc, variable, value); + + if (is_vector(car(env))) { + int location = hash_fn(symname(variable), ivalue_unchecked(car(env))); + + set_vector_elem(car(env), location, + immutable_cons(sc, slot, vector_elem(car(env), location))); + } else { + car(env) = immutable_cons(sc, slot, car(env)); + } +} + +static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all) +{ + pointer x,y; + int location; + + for (x = env; x != sc->NIL; x = cdr(x)) { + if (is_vector(car(x))) { + location = hash_fn(symname(hdl), ivalue_unchecked(car(x))); + y = vector_elem(car(x), location); + } else { + y = car(x); + } + for ( ; y != sc->NIL; y = cdr(y)) { + if (caar(y) == hdl) { + break; + } + } + if (y != sc->NIL) { + break; + } + if(!all) { + return sc->NIL; + } + } + if (x != sc->NIL) { + return car(y); + } + return sc->NIL; +} + +#else /* USE_ALIST_ENV */ + +static INLINE void new_frame_in_env(scheme *sc, pointer old_env) +{ + sc->envir = immutable_cons(sc, sc->NIL, old_env); + setenvironment(sc->envir); +} + +static INLINE void new_slot_spec_in_env(scheme *sc, pointer env, + pointer variable, pointer value) +{ + car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env)); +} + +static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all) +{ + pointer x,y; + for (x = env; x != sc->NIL; x = cdr(x)) { + for (y = car(x); y != sc->NIL; y = cdr(y)) { + if (caar(y) == hdl) { + break; + } + } + if (y != sc->NIL) { + break; + } + if(!all) { + return sc->NIL; + } + } + if (x != sc->NIL) { + return car(y); + } + return sc->NIL; +} + +#endif /* USE_ALIST_ENV else */ + +static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value) +{ + new_slot_spec_in_env(sc, sc->envir, variable, value); +} + +static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value) +{ + cdr(slot) = value; +} + +static INLINE pointer slot_value_in_env(pointer slot) +{ + return cdr(slot); +} + +/* ========== Evaluation Cycle ========== */ + + +static pointer _Error_1(scheme *sc, const char *s, pointer a) { + const char *str = s; +#if USE_ERROR_HOOK + pointer x; + pointer hdl=sc->ERROR_HOOK; +#endif + +#if SHOW_ERROR_LINE + char sbuf[STRBUFFSIZE]; + + /* make sure error is not in REPL */ + if (sc->load_stack[sc->file_i].kind & port_file && + sc->load_stack[sc->file_i].rep.stdio.file != stdin) { + int ln = sc->load_stack[sc->file_i].rep.stdio.curr_line; + const char *fname = sc->load_stack[sc->file_i].rep.stdio.filename; + + /* should never happen */ + if(!fname) fname = ""; + + /* we started from 0 */ + ln++; + snprintf(sbuf, STRBUFFSIZE, "(%s : %i) %s", fname, ln, s); + + str = (const char*)sbuf; + } +#endif + +#if USE_ERROR_HOOK + x=find_slot_in_env(sc,sc->envir,hdl,1); + if (x != sc->NIL) { + if(a!=0) { + sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL); + } else { + sc->code = sc->NIL; + } + sc->code = cons(sc, mk_string(sc, str), sc->code); + setimmutable(car(sc->code)); + sc->code = cons(sc, slot_value_in_env(x), sc->code); + sc->op = (int)OP_EVAL; + return sc->T; + } +#endif + + if(a!=0) { + sc->args = cons(sc, (a), sc->NIL); + } else { + sc->args = sc->NIL; + } + sc->args = cons(sc, mk_string(sc, str), sc->args); + setimmutable(car(sc->args)); + sc->op = (int)OP_ERR0; + return sc->T; +} +#define Error_1(sc,s, a) return _Error_1(sc,s,a) +#define Error_0(sc,s) return _Error_1(sc,s,0) + +/* Too small to turn into function */ +# define BEGIN do { +# define END } while (0) +#define s_goto(sc,a) BEGIN \ + sc->op = (int)(a); \ + return sc->T; END + +#define s_return(sc,a) return _s_return(sc,a) + +#ifndef USE_SCHEME_STACK + +/* this structure holds all the interpreter's registers */ +struct dump_stack_frame { + enum scheme_opcodes op; + pointer args; + pointer envir; + pointer code; +}; + +#define STACK_GROWTH 3 + +static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) +{ + int nframes = (int)sc->dump; + struct dump_stack_frame *next_frame; + + /* enough room for the next frame? */ + if (nframes >= sc->dump_size) { + sc->dump_size += STACK_GROWTH; + /* alas there is no sc->realloc */ + sc->dump_base = realloc(sc->dump_base, + sizeof(struct dump_stack_frame) * sc->dump_size); + } + next_frame = (struct dump_stack_frame *)sc->dump_base + nframes; + next_frame->op = op; + next_frame->args = args; + next_frame->envir = sc->envir; + next_frame->code = code; + sc->dump = (pointer)(nframes+1); +} + +static pointer _s_return(scheme *sc, pointer a) +{ + int nframes = (int)sc->dump; + struct dump_stack_frame *frame; + + sc->value = (a); + if (nframes <= 0) { + return sc->NIL; + } + nframes--; + frame = (struct dump_stack_frame *)sc->dump_base + nframes; + sc->op = frame->op; + sc->args = frame->args; + sc->envir = frame->envir; + sc->code = frame->code; + sc->dump = (pointer)nframes; + return sc->T; +} + +static INLINE void dump_stack_reset(scheme *sc) +{ + /* in this implementation, sc->dump is the number of frames on the stack */ + sc->dump = (pointer)0; +} + +static INLINE void dump_stack_initialize(scheme *sc) +{ + sc->dump_size = 0; + sc->dump_base = NULL; + dump_stack_reset(sc); +} + +static void dump_stack_free(scheme *sc) +{ + free(sc->dump_base); + sc->dump_base = NULL; + sc->dump = (pointer)0; + sc->dump_size = 0; +} + +static INLINE void dump_stack_mark(scheme *sc) +{ + int nframes = (int)sc->dump; + int i; + for(i=0; idump_base + i; + mark(frame->args); + mark(frame->envir); + mark(frame->code); + } +} + +#else + +static INLINE void dump_stack_reset(scheme *sc) +{ + sc->dump = sc->NIL; +} + +static INLINE void dump_stack_initialize(scheme *sc) +{ + dump_stack_reset(sc); +} + +static void dump_stack_free(scheme *sc) +{ + sc->dump = sc->NIL; +} + +static pointer _s_return(scheme *sc, pointer a) { + sc->value = (a); + if(sc->dump==sc->NIL) return sc->NIL; + sc->op = ivalue(car(sc->dump)); + sc->args = cadr(sc->dump); + sc->envir = caddr(sc->dump); + sc->code = cadddr(sc->dump); + sc->dump = cddddr(sc->dump); + return sc->T; +} + +static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) { + if (debug) { fprintf(stderr,"[DEBUG] s_save 1\n"); } + sc->dump = cons(sc, sc->envir, cons(sc, (code), sc->dump)); + if (debug) { fprintf(stderr,"[DEBUG] s_save 2\n"); } + /* crash */ + sc->dump = cons(sc, (args), sc->dump); + if (debug) { fprintf(stderr,"[DEBUG] s_save 3\n"); } + sc->dump = cons(sc, mk_integer(sc, (long)(op)), sc->dump); + if (debug) { fprintf(stderr,"[DEBUG] s_save done\n"); } +} + +static INLINE void dump_stack_mark(scheme *sc) +{ + mark(sc->dump); +} +#endif + +#define s_retbool(tf) s_return(sc,(tf) ? sc->T : sc->F) + +static pointer opexe_0(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + + switch (op) { + case OP_LOAD: /* load */ + if(file_interactive(sc)) { + fprintf(sc->outport->_object._port->rep.stdio.file, + "Loading %s\n", strvalue(car(sc->args))); + } + if (!file_push(sc,strvalue(car(sc->args)))) { + Error_1(sc,"unable to open", car(sc->args)); + } + else + { + sc->args = mk_integer(sc,sc->file_i); + s_goto(sc,OP_T0LVL); + } + + case OP_T0LVL: /* top level */ + /* If we reached the end of file, this loop is done. */ + if(sc->loadport->_object._port->kind & port_saw_EOF) + { + if(sc->file_i == 0) + { + sc->args=sc->NIL; + s_goto(sc,OP_QUIT); + } + else + { + file_pop(sc); + s_return(sc,sc->value); + } + /* NOTREACHED */ + } + + /* If interactive, be nice to user. */ + if(file_interactive(sc)) + { + sc->envir = sc->global_env; + dump_stack_reset(sc); + putstr(sc,"\n"); + putstr(sc,prompt); + } + + /* Set up another iteration of REPL */ + sc->nesting=0; + sc->save_inport=sc->inport; + sc->inport = sc->loadport; + s_save(sc,OP_T0LVL, sc->NIL, sc->NIL); + s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL); + s_save(sc,OP_T1LVL, sc->NIL, sc->NIL); + s_goto(sc,OP_READ_INTERNAL); + + case OP_T1LVL: /* top level */ + sc->code = sc->value; + sc->inport=sc->save_inport; + s_goto(sc,OP_EVAL); + + case OP_READ_INTERNAL: /* internal read */ + sc->tok = token(sc); + if(sc->tok==TOK_EOF) + { s_return(sc,sc->EOF_OBJ); } + s_goto(sc,OP_RDSEXPR); + + case OP_GENSYM: + s_return(sc, gensym(sc)); + + case OP_VALUEPRINT: /* print evaluation result */ + /* OP_VALUEPRINT is always pushed, because when changing from + non-interactive to interactive mode, it needs to be + already on the stack */ + if(sc->tracing) { + putstr(sc,"\nGives: "); + } + if(file_interactive(sc)) { + sc->print_flag = 1; + sc->args = sc->value; + s_goto(sc,OP_P0LIST); + } else { + s_return(sc,sc->value); + } + + case OP_EVAL: /* main part of evaluation */ +#if USE_TRACING + if(sc->tracing) { + /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/ + s_save(sc,OP_REAL_EVAL,sc->args,sc->code); + sc->args=sc->code; + putstr(sc,"\nEval: "); + s_goto(sc,OP_P0LIST); + } + /* fall through */ + case OP_REAL_EVAL: +#endif + if (debug) { fprintf(stderr,"[DEBUG] op_real_eval code [%p]\n",(void*)sc->code); } + if (debug) { fprintf(stderr,"[DEBUG] op_real_eval code type [%d]\n",typeflag(sc->code)); } + if (is_symbol(sc->code)) { /* symbol */ + x=find_slot_in_env(sc,sc->envir,sc->code,1); + if (x != sc->NIL) { + s_return(sc,slot_value_in_env(x)); + } else { + Error_1(sc,"eval: unbound variable:", sc->code); + } + } else if (is_pair(sc->code)) { + if (is_syntax(x = car(sc->code))) { /* SYNTAX */ + sc->code = cdr(sc->code); + s_goto(sc,syntaxnum(x)); + } else {/* first, eval top element and eval arguments */ + if (debug) { fprintf(stderr,"[DEBUG] evaluating application\n"); } + if (debug) { fprintf(stderr,"[DEBUG] sc->NIL=[%p]\n", (void*)sc->NIL); } + if (debug) { fprintf(stderr,"[DEBUG] typeflag(sc->NIL)=[%d]\n", typeflag(sc->NIL)); } + s_save(sc,OP_E0ARGS, sc->NIL, sc->code); + if (debug) { fprintf(stderr,"[DEBUG] s_save complete\n"); } + /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/ + sc->code = car(sc->code); + if (debug) { fprintf(stderr,"[DEBUG] new code [%p]\n", (void*)sc->code); } + if (debug) { fprintf(stderr,"[DEBUG] new code type [%d]\n", typeflag(sc->code)); } + s_goto(sc,OP_EVAL); + } + } else { + s_return(sc,sc->code); + } + + case OP_E0ARGS: /* eval arguments */ + if (is_macro(sc->value)) { /* macro expansion */ + s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL); + sc->args = cons(sc,sc->code, sc->NIL); + sc->code = sc->value; + s_goto(sc,OP_APPLY); + } else { + sc->code = cdr(sc->code); + s_goto(sc,OP_E1ARGS); + } + + case OP_E1ARGS: /* eval arguments */ + sc->args = cons(sc, sc->value, sc->args); + if (is_pair(sc->code)) { /* continue */ + s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code)); + sc->code = car(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->args = reverse_in_place(sc, sc->NIL, sc->args); + sc->code = car(sc->args); + sc->args = cdr(sc->args); + s_goto(sc,OP_APPLY); + } + +#if USE_TRACING + case OP_TRACING: { + int tr=sc->tracing; + sc->tracing=ivalue(car(sc->args)); + s_return(sc,mk_integer(sc,tr)); + } +#endif + + case OP_APPLY: /* apply 'code' to 'args' */ +#if USE_TRACING + if(sc->tracing) { + s_save(sc,OP_REAL_APPLY,sc->args,sc->code); + sc->print_flag = 1; + /* sc->args=cons(sc,sc->code,sc->args);*/ + putstr(sc,"\nApply to: "); + s_goto(sc,OP_P0LIST); + } + /* fall through */ + case OP_REAL_APPLY: +#endif + if (is_proc(sc->code)) { + s_goto(sc,procnum(sc->code)); /* PROCEDURE */ + } else if (is_foreign(sc->code)) + { + /* Keep nested calls from GC'ing the arglist */ + push_recent_alloc(sc,sc->args,sc->NIL); + x=sc->code->_object._ff(sc,sc->args); + s_return(sc,x); + } else if (is_closure(sc->code) || is_macro(sc->code) + || is_promise(sc->code)) { /* CLOSURE */ + /* Should not accept promise */ + /* make environment */ + new_frame_in_env(sc, closure_env(sc->code)); + for (x = car(closure_code(sc->code)), y = sc->args; + is_pair(x); x = cdr(x), y = cdr(y)) { + if (y == sc->NIL) { + Error_0(sc,"not enough arguments"); + } else { + new_slot_in_env(sc, car(x), car(y)); + } + } + if (x == sc->NIL) { + /*-- + * if (y != sc->NIL) { + * Error_0(sc,"too many arguments"); + * } + */ + } else if (is_symbol(x)) + new_slot_in_env(sc, x, y); + else { + Error_1(sc,"syntax error in closure: not a symbol:", x); + } + sc->code = cdr(closure_code(sc->code)); + sc->args = sc->NIL; + s_goto(sc,OP_BEGIN); + } else if (is_continuation(sc->code)) { /* CONTINUATION */ + sc->dump = cont_dump(sc->code); + s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL); + } else { + Error_0(sc,"illegal function"); + } + + case OP_DOMACRO: /* do macro */ + sc->code = sc->value; + s_goto(sc,OP_EVAL); + +#if 1 + case OP_LAMBDA: /* lambda */ + /* If the hook is defined, apply it to sc->code, otherwise + set sc->value fall thru */ + { + pointer f=find_slot_in_env(sc,sc->envir,sc->COMPILE_HOOK,1); + if(f==sc->NIL) { + sc->value = sc->code; + /* Fallthru */ + } else { + s_save(sc,OP_LAMBDA1,sc->args,sc->code); + sc->args=cons(sc,sc->code,sc->NIL); + sc->code=slot_value_in_env(f); + s_goto(sc,OP_APPLY); + } + } + + case OP_LAMBDA1: + s_return(sc,mk_closure(sc, sc->value, sc->envir)); + +#else + case OP_LAMBDA: /* lambda */ + s_return(sc,mk_closure(sc, sc->code, sc->envir)); + +#endif + + case OP_MKCLOSURE: /* make-closure */ + x=car(sc->args); + if(car(x)==sc->LAMBDA) { + x=cdr(x); + } + if(cdr(sc->args)==sc->NIL) { + y=sc->envir; + } else { + y=cadr(sc->args); + } + s_return(sc,mk_closure(sc, x, y)); + + case OP_QUOTE: /* quote */ + s_return(sc,car(sc->code)); + + case OP_DEF0: /* define */ + if(is_immutable(car(sc->code))) + Error_1(sc,"define: unable to alter immutable", car(sc->code)); + + if (is_pair(car(sc->code))) { + x = caar(sc->code); + sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code))); + } else { + x = car(sc->code); + sc->code = cadr(sc->code); + } + if (!is_symbol(x)) { + Error_0(sc,"variable is not a symbol"); + } + s_save(sc,OP_DEF1, sc->NIL, x); + s_goto(sc,OP_EVAL); + + case OP_DEF1: /* define */ + x=find_slot_in_env(sc,sc->envir,sc->code,0); + if (x != sc->NIL) { + set_slot_in_env(sc, x, sc->value); + } else { + new_slot_in_env(sc, sc->code, sc->value); + } + s_return(sc,sc->code); + + + case OP_DEFP: /* defined? */ + x=sc->envir; + if(cdr(sc->args)!=sc->NIL) { + x=cadr(sc->args); + } + s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL); + + case OP_SET0: /* set! */ + if(is_immutable(car(sc->code))) + Error_1(sc,"set!: unable to alter immutable variable",car(sc->code)); + s_save(sc,OP_SET1, sc->NIL, car(sc->code)); + sc->code = cadr(sc->code); + s_goto(sc,OP_EVAL); + + case OP_SET1: /* set! */ + y=find_slot_in_env(sc,sc->envir,sc->code,1); + if (y != sc->NIL) { + set_slot_in_env(sc, y, sc->value); + s_return(sc,sc->value); + } else { + Error_1(sc,"set!: unbound variable:", sc->code); + } + + + case OP_BEGIN: /* begin */ + if (!is_pair(sc->code)) { + s_return(sc,sc->code); + } + if (cdr(sc->code) != sc->NIL) { + s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code)); + } + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_IF0: /* if */ + s_save(sc,OP_IF1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_IF1: /* if */ + if (is_true(sc->value)) + sc->code = car(sc->code); + else + sc->code = cadr(sc->code); /* (if #f 1) ==> () because + * car(sc->NIL) = sc->NIL */ + s_goto(sc,OP_EVAL); + + case OP_LET0: /* let */ + sc->args = sc->NIL; + sc->value = sc->code; + sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code); + s_goto(sc,OP_LET1); + + case OP_LET1: /* let (calculate parameters) */ + sc->args = cons(sc, sc->value, sc->args); + if (is_pair(sc->code)) { /* continue */ + if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) { + Error_1(sc, "Bad syntax of binding spec in let :", + car(sc->code)); + } + s_save(sc,OP_LET1, sc->args, cdr(sc->code)); + sc->code = cadar(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->args = reverse_in_place(sc, sc->NIL, sc->args); + sc->code = car(sc->args); + sc->args = cdr(sc->args); + s_goto(sc,OP_LET2); + } + + case OP_LET2: /* let */ + new_frame_in_env(sc, sc->envir); + for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args; + y != sc->NIL; x = cdr(x), y = cdr(y)) { + new_slot_in_env(sc, caar(x), car(y)); + } + if (is_symbol(car(sc->code))) { /* named let */ + for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) { + if (!is_pair(x)) + Error_1(sc, "Bad syntax of binding in let :", x); + if (!is_list(sc, car(x))) + Error_1(sc, "Bad syntax of binding in let :", car(x)); + sc->args = cons(sc, caar(x), sc->args); + } + x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir); + new_slot_in_env(sc, car(sc->code), x); + sc->code = cddr(sc->code); + sc->args = sc->NIL; + } else { + sc->code = cdr(sc->code); + sc->args = sc->NIL; + } + s_goto(sc,OP_BEGIN); + + case OP_LET0AST: /* let* */ + if (car(sc->code) == sc->NIL) { + new_frame_in_env(sc, sc->envir); + sc->code = cdr(sc->code); + s_goto(sc,OP_BEGIN); + } + if(!is_pair(car(sc->code)) || !is_pair(caar(sc->code)) || !is_pair(cdaar(sc->code))) { + Error_1(sc,"Bad syntax of binding spec in let* :",car(sc->code)); + } + s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code)); + sc->code = cadaar(sc->code); + s_goto(sc,OP_EVAL); + + case OP_LET1AST: /* let* (make new frame) */ + new_frame_in_env(sc, sc->envir); + s_goto(sc,OP_LET2AST); + + case OP_LET2AST: /* let* (calculate parameters) */ + new_slot_in_env(sc, caar(sc->code), sc->value); + sc->code = cdr(sc->code); + if (is_pair(sc->code)) { /* continue */ + s_save(sc,OP_LET2AST, sc->args, sc->code); + sc->code = cadar(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->code = sc->args; + sc->args = sc->NIL; + s_goto(sc,OP_BEGIN); + } + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static pointer opexe_1(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + + switch (op) { + case OP_LET0REC: /* letrec */ + new_frame_in_env(sc, sc->envir); + sc->args = sc->NIL; + sc->value = sc->code; + sc->code = car(sc->code); + s_goto(sc,OP_LET1REC); + + case OP_LET1REC: /* letrec (calculate parameters) */ + sc->args = cons(sc, sc->value, sc->args); + if (is_pair(sc->code)) { /* continue */ + if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) { + Error_1(sc, "Bad syntax of binding spec in letrec :", + car(sc->code)); + } + s_save(sc,OP_LET1REC, sc->args, cdr(sc->code)); + sc->code = cadar(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_EVAL); + } else { /* end */ + sc->args = reverse_in_place(sc, sc->NIL, sc->args); + sc->code = car(sc->args); + sc->args = cdr(sc->args); + s_goto(sc,OP_LET2REC); + } + + case OP_LET2REC: /* letrec */ + for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) { + new_slot_in_env(sc, caar(x), car(y)); + } + sc->code = cdr(sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_BEGIN); + + case OP_COND0: /* cond */ + if (!is_pair(sc->code)) { + Error_0(sc,"syntax error in cond"); + } + s_save(sc,OP_COND1, sc->NIL, sc->code); + sc->code = caar(sc->code); + s_goto(sc,OP_EVAL); + + case OP_COND1: /* cond */ + if (is_true(sc->value)) { + if ((sc->code = cdar(sc->code)) == sc->NIL) { + s_return(sc,sc->value); + } + if(car(sc->code)==sc->FEED_TO) { + if(!is_pair(cdr(sc->code))) { + Error_0(sc,"syntax error in cond"); + } + x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL)); + sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL)); + s_goto(sc,OP_EVAL); + } + s_goto(sc,OP_BEGIN); + } else { + if ((sc->code = cdr(sc->code)) == sc->NIL) { + s_return(sc,sc->NIL); + } else { + s_save(sc,OP_COND1, sc->NIL, sc->code); + sc->code = caar(sc->code); + s_goto(sc,OP_EVAL); + } + } + + case OP_DELAY: /* delay */ + x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir); + typeflag(x)=T_PROMISE; + s_return(sc,x); + + case OP_AND0: /* and */ + if (sc->code == sc->NIL) { + s_return(sc,sc->T); + } + s_save(sc,OP_AND1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_AND1: /* and */ + if (is_false(sc->value)) { + s_return(sc,sc->value); + } else if (sc->code == sc->NIL) { + s_return(sc,sc->value); + } else { + s_save(sc,OP_AND1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + } + + case OP_OR0: /* or */ + if (sc->code == sc->NIL) { + s_return(sc,sc->F); + } + s_save(sc,OP_OR1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_OR1: /* or */ + if (is_true(sc->value)) { + s_return(sc,sc->value); + } else if (sc->code == sc->NIL) { + s_return(sc,sc->value); + } else { + s_save(sc,OP_OR1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + } + + case OP_C0STREAM: /* cons-stream */ + s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_C1STREAM: /* cons-stream */ + sc->args = sc->value; /* save sc->value to register sc->args for gc */ + x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir); + typeflag(x)=T_PROMISE; + s_return(sc,cons(sc, sc->args, x)); + + case OP_MACRO0: /* macro */ + if (is_pair(car(sc->code))) { + x = caar(sc->code); + sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code))); + } else { + x = car(sc->code); + sc->code = cadr(sc->code); + } + if (!is_symbol(x)) { + Error_0(sc,"variable is not a symbol"); + } + s_save(sc,OP_MACRO1, sc->NIL, x); + s_goto(sc,OP_EVAL); + + case OP_MACRO1: /* macro */ + typeflag(sc->value) = T_MACRO; + x = find_slot_in_env(sc, sc->envir, sc->code, 0); + if (x != sc->NIL) { + set_slot_in_env(sc, x, sc->value); + } else { + new_slot_in_env(sc, sc->code, sc->value); + } + s_return(sc,sc->code); + + case OP_CASE0: /* case */ + s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code)); + sc->code = car(sc->code); + s_goto(sc,OP_EVAL); + + case OP_CASE1: /* case */ + for (x = sc->code; x != sc->NIL; x = cdr(x)) { + if (!is_pair(y = caar(x))) { + break; + } + for ( ; y != sc->NIL; y = cdr(y)) { + if (eqv(car(y), sc->value)) { + break; + } + } + if (y != sc->NIL) { + break; + } + } + if (x != sc->NIL) { + if (is_pair(caar(x))) { + sc->code = cdar(x); + s_goto(sc,OP_BEGIN); + } else {/* else */ + s_save(sc,OP_CASE2, sc->NIL, cdar(x)); + sc->code = caar(x); + s_goto(sc,OP_EVAL); + } + } else { + s_return(sc,sc->NIL); + } + + case OP_CASE2: /* case */ + if (is_true(sc->value)) { + s_goto(sc,OP_BEGIN); + } else { + s_return(sc,sc->NIL); + } + + case OP_PAPPLY: /* apply */ + sc->code = car(sc->args); + sc->args = list_star(sc,cdr(sc->args)); + /*sc->args = cadr(sc->args);*/ + s_goto(sc,OP_APPLY); + + case OP_PEVAL: /* eval */ + if(cdr(sc->args)!=sc->NIL) { + sc->envir=cadr(sc->args); + } + sc->code = car(sc->args); + s_goto(sc,OP_EVAL); + + case OP_CONTINUATION: /* call-with-current-continuation */ + sc->code = car(sc->args); + sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL); + s_goto(sc,OP_APPLY); + + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static pointer opexe_2(scheme *sc, enum scheme_opcodes op) { + pointer x; + num v; +#if USE_MATH + double dd; +#endif + + switch (op) { +#if USE_MATH + case OP_INEX2EX: /* inexact->exact */ + x=car(sc->args); + if(num_is_integer(x)) { + s_return(sc,x); + } else if(modf(rvalue_unchecked(x),&dd)==0.0) { + s_return(sc,mk_integer(sc,ivalue(x))); + } else { + Error_1(sc,"inexact->exact: not integral:",x); + } + + case OP_EXP: + x=car(sc->args); + s_return(sc, mk_real(sc, exp(rvalue(x)))); + + case OP_LOG: + x=car(sc->args); + s_return(sc, mk_real(sc, log(rvalue(x)))); + + case OP_SIN: + x=car(sc->args); + s_return(sc, mk_real(sc, sin(rvalue(x)))); + + case OP_COS: + x=car(sc->args); + s_return(sc, mk_real(sc, cos(rvalue(x)))); + + case OP_TAN: + x=car(sc->args); + s_return(sc, mk_real(sc, tan(rvalue(x)))); + + case OP_ASIN: + x=car(sc->args); + s_return(sc, mk_real(sc, asin(rvalue(x)))); + + case OP_ACOS: + x=car(sc->args); + s_return(sc, mk_real(sc, acos(rvalue(x)))); + + case OP_ATAN: + x=car(sc->args); + if(cdr(sc->args)==sc->NIL) { + s_return(sc, mk_real(sc, atan(rvalue(x)))); + } else { + pointer y=cadr(sc->args); + s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y)))); + } + + case OP_SQRT: + x=car(sc->args); + s_return(sc, mk_real(sc, sqrt(rvalue(x)))); + + case OP_EXPT: { + double result; + int real_result=1; + pointer y=cadr(sc->args); + x=car(sc->args); + if (num_is_integer(x) && num_is_integer(y)) + real_result=0; + /* This 'if' is an R5RS compatibility fix. */ + /* NOTE: Remove this 'if' fix for R6RS. */ + if (rvalue(x) == 0 && rvalue(y) < 0) { + result = 0.0; + } else { + result = pow(rvalue(x),rvalue(y)); + } + /* Before returning integer result make sure we can. */ + /* If the test fails, result is too big for integer. */ + if (!real_result) + { + long result_as_long = (long)result; + if (result != (double)result_as_long) + real_result = 1; + } + if (real_result) { + s_return(sc, mk_real(sc, result)); + } else { + s_return(sc, mk_integer(sc, result)); + } + } + + case OP_FLOOR: + x=car(sc->args); + s_return(sc, mk_real(sc, floor(rvalue(x)))); + + case OP_CEILING: + x=car(sc->args); + s_return(sc, mk_real(sc, ceil(rvalue(x)))); + + case OP_TRUNCATE : { + double rvalue_of_x ; + x=car(sc->args); + rvalue_of_x = rvalue(x) ; + if (rvalue_of_x > 0) { + s_return(sc, mk_real(sc, floor(rvalue_of_x))); + } else { + s_return(sc, mk_real(sc, ceil(rvalue_of_x))); + } + } + + case OP_ROUND: + x=car(sc->args); + if (num_is_integer(x)) + s_return(sc, x); + s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x)))); +#endif + + case OP_ADD: /* + */ + v=num_zero; + for (x = sc->args; x != sc->NIL; x = cdr(x)) { + v=num_add(v,nvalue(car(x))); + } + s_return(sc,mk_number(sc, v)); + + case OP_MUL: /* * */ + v=num_one; + for (x = sc->args; x != sc->NIL; x = cdr(x)) { + v=num_mul(v,nvalue(car(x))); + } + s_return(sc,mk_number(sc, v)); + + case OP_SUB: /* - */ + if(cdr(sc->args)==sc->NIL) { + x=sc->args; + v=num_zero; + } else { + x = cdr(sc->args); + v = nvalue(car(sc->args)); + } + for (; x != sc->NIL; x = cdr(x)) { + v=num_sub(v,nvalue(car(x))); + } + s_return(sc,mk_number(sc, v)); + + case OP_DIV: /* / */ + if(cdr(sc->args)==sc->NIL) { + x=sc->args; + v=num_one; + } else { + x = cdr(sc->args); + v = nvalue(car(sc->args)); + } + for (; x != sc->NIL; x = cdr(x)) { + if (!is_zero_double(rvalue(car(x)))) + v=num_div(v,nvalue(car(x))); + else { + Error_0(sc,"/: division by zero"); + } + } + s_return(sc,mk_number(sc, v)); + + case OP_INTDIV: /* quotient */ + if(cdr(sc->args)==sc->NIL) { + x=sc->args; + v=num_one; + } else { + x = cdr(sc->args); + v = nvalue(car(sc->args)); + } + for (; x != sc->NIL; x = cdr(x)) { + if (ivalue(car(x)) != 0) + v=num_intdiv(v,nvalue(car(x))); + else { + Error_0(sc,"quotient: division by zero"); + } + } + s_return(sc,mk_number(sc, v)); + + case OP_REM: /* remainder */ + v = nvalue(car(sc->args)); + if (ivalue(cadr(sc->args)) != 0) + v=num_rem(v,nvalue(cadr(sc->args))); + else { + Error_0(sc,"remainder: division by zero"); + } + s_return(sc,mk_number(sc, v)); + + case OP_MOD: /* modulo */ + v = nvalue(car(sc->args)); + if (ivalue(cadr(sc->args)) != 0) + v=num_mod(v,nvalue(cadr(sc->args))); + else { + Error_0(sc,"modulo: division by zero"); + } + s_return(sc,mk_number(sc, v)); + + case OP_CAR: /* car */ + s_return(sc,caar(sc->args)); + + case OP_CDR: /* cdr */ + s_return(sc,cdar(sc->args)); + + case OP_CONS: /* cons */ + cdr(sc->args) = cadr(sc->args); + s_return(sc,sc->args); + + case OP_SETCAR: /* set-car! */ + if(!is_immutable(car(sc->args))) { + caar(sc->args) = cadr(sc->args); + s_return(sc,car(sc->args)); + } else { + Error_0(sc,"set-car!: unable to alter immutable pair"); + } + + case OP_SETCDR: /* set-cdr! */ + if(!is_immutable(car(sc->args))) { + cdar(sc->args) = cadr(sc->args); + s_return(sc,car(sc->args)); + } else { + Error_0(sc,"set-cdr!: unable to alter immutable pair"); + } + + case OP_CHAR2INT: { /* char->integer */ + char c; + c=(char)ivalue(car(sc->args)); + s_return(sc,mk_integer(sc,(unsigned char)c)); + } + + case OP_INT2CHAR: { /* integer->char */ + unsigned char c; + c=(unsigned char)ivalue(car(sc->args)); + s_return(sc,mk_character(sc,(char)c)); + } + + case OP_CHARUPCASE: { + unsigned char c; + c=(unsigned char)ivalue(car(sc->args)); + c=toupper(c); + s_return(sc,mk_character(sc,(char)c)); + } + + case OP_CHARDNCASE: { + unsigned char c; + c=(unsigned char)ivalue(car(sc->args)); + c=tolower(c); + s_return(sc,mk_character(sc,(char)c)); + } + + case OP_STR2SYM: /* string->symbol */ + s_return(sc,mk_symbol(sc,strvalue(car(sc->args)))); + + case OP_STR2ATOM: /* string->atom */ { + char *s=strvalue(car(sc->args)); + long pf = 0; + if(cdr(sc->args)!=sc->NIL) { + /* we know cadr(sc->args) is a natural number */ + /* see if it is 2, 8, 10, or 16, or error */ + pf = ivalue_unchecked(cadr(sc->args)); + if(pf == 16 || pf == 10 || pf == 8 || pf == 2) { + /* base is OK */ + } + else { + pf = -1; + } + } + if (pf < 0) { + Error_1(sc, "string->atom: bad base:", cadr(sc->args)); + } else if(*s=='#') /* no use of base! */ { + s_return(sc, mk_sharp_const(sc, s+1)); + } else { + if (pf == 0 || pf == 10) { + s_return(sc, mk_atom(sc, s)); + } + else { + char *ep; + long iv = strtol(s,&ep,(int )pf); + if (*ep == 0) { + s_return(sc, mk_integer(sc, iv)); + } + else { + s_return(sc, sc->F); + } + } + } + } + + case OP_SYM2STR: /* symbol->string */ + x=mk_string(sc,symname(car(sc->args))); + setimmutable(x); + s_return(sc,x); + + case OP_ATOM2STR: /* atom->string */ { + long pf = 0; + x=car(sc->args); + if(cdr(sc->args)!=sc->NIL) { + /* we know cadr(sc->args) is a natural number */ + /* see if it is 2, 8, 10, or 16, or error */ + pf = ivalue_unchecked(cadr(sc->args)); + if(is_number(x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2)) { + /* base is OK */ + } + else { + pf = -1; + } + } + if (pf < 0) { + Error_1(sc, "atom->string: bad base:", cadr(sc->args)); + } else if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) { + char *p; + int len; + atom2str(sc,x,(int )pf,&p,&len); + s_return(sc,mk_counted_string(sc,p,len)); + } else { + Error_1(sc, "atom->string: not an atom:", x); + } + } + + case OP_MKSTRING: { /* make-string */ + int fill=' '; + int len; + + len=ivalue(car(sc->args)); + + if(cdr(sc->args)!=sc->NIL) { + fill=charvalue(cadr(sc->args)); + } + s_return(sc,mk_empty_string(sc,len,(char)fill)); + } + + case OP_STRLEN: /* string-length */ + s_return(sc,mk_integer(sc,strlength(car(sc->args)))); + + case OP_STRREF: { /* string-ref */ + char *str; + int index; + + str=strvalue(car(sc->args)); + + index=ivalue(cadr(sc->args)); + + if(index>=strlength(car(sc->args))) { + Error_1(sc,"string-ref: out of bounds:",cadr(sc->args)); + } + + s_return(sc,mk_character(sc,((unsigned char*)str)[index])); + } + + case OP_STRSET: { /* string-set! */ + char *str; + int index; + int c; + + if(is_immutable(car(sc->args))) { + Error_1(sc,"string-set!: unable to alter immutable string:",car(sc->args)); + } + str=strvalue(car(sc->args)); + + index=ivalue(cadr(sc->args)); + if(index>=strlength(car(sc->args))) { + Error_1(sc,"string-set!: out of bounds:",cadr(sc->args)); + } + + c=charvalue(caddr(sc->args)); + + str[index]=(char)c; + s_return(sc,car(sc->args)); + } + + case OP_STRAPPEND: { /* string-append */ + /* in 1.29 string-append was in Scheme in init.scm but was too slow */ + int len = 0; + pointer newstr; + char *pos; + + /* compute needed length for new string */ + for (x = sc->args; x != sc->NIL; x = cdr(x)) { + len += strlength(car(x)); + } + newstr = mk_empty_string(sc, len, ' '); + /* store the contents of the argument strings into the new string */ + for (pos = strvalue(newstr), x = sc->args; x != sc->NIL; + pos += strlength(car(x)), x = cdr(x)) { + memcpy(pos, strvalue(car(x)), strlength(car(x))); + } + s_return(sc, newstr); + } + + case OP_SUBSTR: { /* substring */ + char *str; + int index0; + int index1; + int len; + + str=strvalue(car(sc->args)); + + index0=ivalue(cadr(sc->args)); + + if(index0>strlength(car(sc->args))) { + Error_1(sc,"substring: start out of bounds:",cadr(sc->args)); + } + + if(cddr(sc->args)!=sc->NIL) { + index1=ivalue(caddr(sc->args)); + if(index1>strlength(car(sc->args)) || index1args)); + } + } else { + index1=strlength(car(sc->args)); + } + + len=index1-index0; + x=mk_empty_string(sc,len,' '); + memcpy(strvalue(x),str+index0,len); + strvalue(x)[len]=0; + + s_return(sc,x); + } + + case OP_VECTOR: { /* vector */ + int i; + pointer vec; + int len=list_length(sc,sc->args); + if(len<0) { + Error_1(sc,"vector: not a proper list:",sc->args); + } + vec=mk_vector(sc,len); + if(sc->no_memory) { s_return(sc, sc->sink); } + for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) { + set_vector_elem(vec,i,car(x)); + } + s_return(sc,vec); + } + + case OP_MKVECTOR: { /* make-vector */ + pointer fill=sc->NIL; + int len; + pointer vec; + + len=ivalue(car(sc->args)); + + if(cdr(sc->args)!=sc->NIL) { + fill=cadr(sc->args); + } + vec=mk_vector(sc,len); + if(sc->no_memory) { s_return(sc, sc->sink); } + if(fill!=sc->NIL) { + fill_vector(vec,fill); + } + s_return(sc,vec); + } + + case OP_VECLEN: /* vector-length */ + s_return(sc,mk_integer(sc,ivalue(car(sc->args)))); + + case OP_VECREF: { /* vector-ref */ + int index; + + index=ivalue(cadr(sc->args)); + + if(index>=ivalue(car(sc->args))) { + Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args)); + } + + s_return(sc,vector_elem(car(sc->args),index)); + } + + case OP_VECSET: { /* vector-set! */ + int index; + + if(is_immutable(car(sc->args))) { + Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args)); + } + + index=ivalue(cadr(sc->args)); + if(index>=ivalue(car(sc->args))) { + Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args)); + } + + set_vector_elem(car(sc->args),index,caddr(sc->args)); + s_return(sc,car(sc->args)); + } + + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static int is_list(scheme *sc, pointer a) +{ return list_length(sc,a) >= 0; } + +/* Result is: + proper list: length + circular list: -1 + not even a pair: -2 + dotted list: -2 minus length before dot +*/ +int list_length(scheme *sc, pointer a) { + int i=0; + pointer slow, fast; + + slow = fast = a; + while (1) + { + if (fast == sc->NIL) + return i; + if (!is_pair(fast)) + return -2 - i; + fast = cdr(fast); + ++i; + if (fast == sc->NIL) + return i; + if (!is_pair(fast)) + return -2 - i; + ++i; + fast = cdr(fast); + + /* Safe because we would have already returned if `fast' + encountered a non-pair. */ + slow = cdr(slow); + if (fast == slow) + { + /* the fast pointer has looped back around and caught up + with the slow pointer, hence the structure is circular, + not of finite length, and therefore not a list */ + return -1; + } + } +} + +static pointer opexe_3(scheme *sc, enum scheme_opcodes op) { + pointer x; + num v; + int (*comp_func)(num,num)=0; + + switch (op) { + case OP_NOT: /* not */ + s_retbool(is_false(car(sc->args))); + case OP_BOOLP: /* boolean? */ + s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T); + case OP_EOFOBJP: /* boolean? */ + s_retbool(car(sc->args) == sc->EOF_OBJ); + case OP_NULLP: /* null? */ + s_retbool(car(sc->args) == sc->NIL); + case OP_NUMEQ: /* = */ + case OP_LESS: /* < */ + case OP_GRE: /* > */ + case OP_LEQ: /* <= */ + case OP_GEQ: /* >= */ + switch(op) { + case OP_NUMEQ: comp_func=num_eq; break; + case OP_LESS: comp_func=num_lt; break; + case OP_GRE: comp_func=num_gt; break; + case OP_LEQ: comp_func=num_le; break; + case OP_GEQ: comp_func=num_ge; break; + } + x=sc->args; + v=nvalue(car(x)); + x=cdr(x); + + for (; x != sc->NIL; x = cdr(x)) { + if(!comp_func(v,nvalue(car(x)))) { + s_retbool(0); + } + v=nvalue(car(x)); + } + s_retbool(1); + case OP_SYMBOLP: /* symbol? */ + s_retbool(is_symbol(car(sc->args))); + case OP_NUMBERP: /* number? */ + s_retbool(is_number(car(sc->args))); + case OP_STRINGP: /* string? */ + s_retbool(is_string(car(sc->args))); + case OP_INTEGERP: /* integer? */ + s_retbool(is_integer(car(sc->args))); + case OP_REALP: /* real? */ + s_retbool(is_number(car(sc->args))); /* All numbers are real */ + case OP_CHARP: /* char? */ + s_retbool(is_character(car(sc->args))); +#if USE_CHAR_CLASSIFIERS + case OP_CHARAP: /* char-alphabetic? */ + s_retbool(Cisalpha(ivalue(car(sc->args)))); + case OP_CHARNP: /* char-numeric? */ + s_retbool(Cisdigit(ivalue(car(sc->args)))); + case OP_CHARWP: /* char-whitespace? */ + s_retbool(Cisspace(ivalue(car(sc->args)))); + case OP_CHARUP: /* char-upper-case? */ + s_retbool(Cisupper(ivalue(car(sc->args)))); + case OP_CHARLP: /* char-lower-case? */ + s_retbool(Cislower(ivalue(car(sc->args)))); +#endif + case OP_PORTP: /* port? */ + s_retbool(is_port(car(sc->args))); + case OP_INPORTP: /* input-port? */ + s_retbool(is_inport(car(sc->args))); + case OP_OUTPORTP: /* output-port? */ + s_retbool(is_outport(car(sc->args))); + case OP_PROCP: /* procedure? */ + /*-- + * continuation should be procedure by the example + * (call-with-current-continuation procedure?) ==> #t + * in R^3 report sec. 6.9 + */ + s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args)) + || is_continuation(car(sc->args)) || is_foreign(car(sc->args))); + case OP_PAIRP: /* pair? */ + s_retbool(is_pair(car(sc->args))); + case OP_LISTP: /* list? */ + s_retbool(list_length(sc,car(sc->args)) >= 0); + + case OP_ENVP: /* environment? */ + s_retbool(is_environment(car(sc->args))); + case OP_VECTORP: /* vector? */ + s_retbool(is_vector(car(sc->args))); + case OP_EQ: /* eq? */ + s_retbool(car(sc->args) == cadr(sc->args)); + case OP_EQV: /* eqv? */ + s_retbool(eqv(car(sc->args), cadr(sc->args))); + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; +} + +static pointer opexe_4(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + + switch (op) { + case OP_FORCE: /* force */ + sc->code = car(sc->args); + if (is_promise(sc->code)) { + /* Should change type to closure here */ + s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code); + sc->args = sc->NIL; + s_goto(sc,OP_APPLY); + } else { + s_return(sc,sc->code); + } + + case OP_SAVE_FORCED: /* Save forced value replacing promise */ + memcpy(sc->code,sc->value,sizeof(struct cell)); + s_return(sc,sc->value); + + case OP_WRITE: /* write */ + case OP_DISPLAY: /* display */ + case OP_WRITE_CHAR: /* write-char */ + if(is_pair(cdr(sc->args))) { + if(cadr(sc->args)!=sc->outport) { + x=cons(sc,sc->outport,sc->NIL); + s_save(sc,OP_SET_OUTPORT, x, sc->NIL); + sc->outport=cadr(sc->args); + } + } + sc->args = car(sc->args); + if(op==OP_WRITE) { + sc->print_flag = 1; + } else { + sc->print_flag = 0; + } + s_goto(sc,OP_P0LIST); + + case OP_NEWLINE: /* newline */ + if(is_pair(sc->args)) { + if(car(sc->args)!=sc->outport) { + x=cons(sc,sc->outport,sc->NIL); + s_save(sc,OP_SET_OUTPORT, x, sc->NIL); + sc->outport=car(sc->args); + } + } + putstr(sc, "\n"); + s_return(sc,sc->T); + + case OP_ERR0: /* error */ + sc->retcode=-1; + if (!is_string(car(sc->args))) { + sc->args=cons(sc,mk_string(sc," -- "),sc->args); + setimmutable(car(sc->args)); + } + putstr(sc, "Error: "); + putstr(sc, strvalue(car(sc->args))); + fprintf(stderr,"[DEBUG] Eval_Cycle_Count=%lld\n",Eval_Cycle_Count); + sc->args = cdr(sc->args); + s_goto(sc,OP_ERR1); + + case OP_ERR1: /* error */ + putstr(sc, " "); + if (sc->args != sc->NIL) { + s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL); + sc->args = car(sc->args); + sc->print_flag = 1; + s_goto(sc,OP_P0LIST); + } else { + putstr(sc, "\n"); + if(sc->interactive_repl) { + s_goto(sc,OP_T0LVL); + } else { + return sc->NIL; + } + } + + case OP_REVERSE: /* reverse */ + s_return(sc,reverse(sc, car(sc->args))); + + case OP_LIST_STAR: /* list* */ + s_return(sc,list_star(sc,sc->args)); + + case OP_APPEND: /* append */ + x = sc->NIL; + y = sc->args; + if (y == x) { + s_return(sc, x); + } + + /* cdr() in the while condition is not a typo. If car() */ + /* is used (append '() 'a) will return the wrong result.*/ + while (cdr(y) != sc->NIL) { + x = revappend(sc, x, car(y)); + y = cdr(y); + if (x == sc->F) { + Error_0(sc, "non-list argument to append"); + } + } + + s_return(sc, reverse_in_place(sc, car(y), x)); + +#if USE_PLIST + case OP_PUT: /* put */ + if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) { + Error_0(sc,"illegal use of put"); + } + for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) { + if (caar(x) == y) { + break; + } + } + if (x != sc->NIL) + cdar(x) = caddr(sc->args); + else + symprop(car(sc->args)) = cons(sc, cons(sc, y, caddr(sc->args)), + symprop(car(sc->args))); + s_return(sc,sc->T); + + case OP_GET: /* get */ + if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) { + Error_0(sc,"illegal use of get"); + } + for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) { + if (caar(x) == y) { + break; + } + } + if (x != sc->NIL) { + s_return(sc,cdar(x)); + } else { + s_return(sc,sc->NIL); + } +#endif /* USE_PLIST */ + case OP_QUIT: /* quit */ + if(is_pair(sc->args)) { + sc->retcode=ivalue(car(sc->args)); + } + return (sc->NIL); + + case OP_GC: /* gc */ + gc(sc, sc->NIL, sc->NIL); + s_return(sc,sc->T); + + case OP_GCVERB: /* gc-verbose */ + { int was = sc->gc_verbose; + sc->gc_verbose = (car(sc->args) != sc->F); + s_retbool(was); + } + + case OP_NEWSEGMENT: /* new-segment */ + if (!is_pair(sc->args) || !is_number(car(sc->args))) { + Error_0(sc,"new-segment: argument must be a number"); + } + alloc_cellseg(sc, (int) ivalue(car(sc->args))); + s_return(sc,sc->T); + + case OP_OBLIST: /* oblist */ + s_return(sc, oblist_all_symbols(sc)); + + case OP_CURR_INPORT: /* current-input-port */ + s_return(sc,sc->inport); + + case OP_CURR_OUTPORT: /* current-output-port */ + s_return(sc,sc->outport); + + case OP_OPEN_INFILE: /* open-input-file */ + case OP_OPEN_OUTFILE: /* open-output-file */ + case OP_OPEN_INOUTFILE: /* open-input-output-file */ { + int prop=0; + pointer p; + switch(op) { + case OP_OPEN_INFILE: prop=port_input; break; + case OP_OPEN_OUTFILE: prop=port_output; break; + case OP_OPEN_INOUTFILE: prop=port_input|port_output; break; + } + p=port_from_filename(sc,strvalue(car(sc->args)),prop); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + s_return(sc,p); + } + +#if USE_STRING_PORTS + case OP_OPEN_INSTRING: /* open-input-string */ + case OP_OPEN_INOUTSTRING: /* open-input-output-string */ { + int prop=0; + pointer p; + switch(op) { + case OP_OPEN_INSTRING: prop=port_input; break; + case OP_OPEN_INOUTSTRING: prop=port_input|port_output; break; + } + p=port_from_string(sc, strvalue(car(sc->args)), + strvalue(car(sc->args))+strlength(car(sc->args)), prop); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + s_return(sc,p); + } + case OP_OPEN_OUTSTRING: /* open-output-string */ { + pointer p; + if(car(sc->args)==sc->NIL) { + p=port_from_scratch(sc); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + } else { + p=port_from_string(sc, strvalue(car(sc->args)), + strvalue(car(sc->args))+strlength(car(sc->args)), + port_output); + if(p==sc->NIL) { + s_return(sc,sc->F); + } + } + s_return(sc,p); + } + case OP_GET_OUTSTRING: /* get-output-string */ { + port *p; + + if ((p=car(sc->args)->_object._port)->kind&port_string) { + off_t size; + char *str; + + size=p->rep.string.curr-p->rep.string.start+1; + str=sc->malloc(size); + if(str != NULL) { + pointer s; + + memcpy(str,p->rep.string.start,size-1); + str[size-1]='\0'; + s=mk_string(sc,str); + sc->free(str); + s_return(sc,s); + } + } + s_return(sc,sc->F); + } +#endif + + case OP_CLOSE_INPORT: /* close-input-port */ + port_close(sc,car(sc->args),port_input); + s_return(sc,sc->T); + + case OP_CLOSE_OUTPORT: /* close-output-port */ + port_close(sc,car(sc->args),port_output); + s_return(sc,sc->T); + + case OP_INT_ENV: /* interaction-environment */ + s_return(sc,sc->global_env); + + case OP_CURR_ENV: /* current-environment */ + s_return(sc,sc->envir); + + } + return sc->T; +} + +static pointer opexe_5(scheme *sc, enum scheme_opcodes op) { + pointer x; + + if(sc->nesting!=0) { + int n=sc->nesting; + sc->nesting=0; + sc->retcode=-1; + Error_1(sc,"unmatched parentheses:",mk_integer(sc,n)); + } + + switch (op) { + /* ========== reading part ========== */ + case OP_READ: + if(!is_pair(sc->args)) { + s_goto(sc,OP_READ_INTERNAL); + } + if(!is_inport(car(sc->args))) { + Error_1(sc,"read: not an input port:",car(sc->args)); + } + if(car(sc->args)==sc->inport) { + s_goto(sc,OP_READ_INTERNAL); + } + x=sc->inport; + sc->inport=car(sc->args); + x=cons(sc,x,sc->NIL); + s_save(sc,OP_SET_INPORT, x, sc->NIL); + s_goto(sc,OP_READ_INTERNAL); + + case OP_READ_CHAR: /* read-char */ + case OP_PEEK_CHAR: /* peek-char */ { + int c; + if(is_pair(sc->args)) { + if(car(sc->args)!=sc->inport) { + x=sc->inport; + x=cons(sc,x,sc->NIL); + s_save(sc,OP_SET_INPORT, x, sc->NIL); + sc->inport=car(sc->args); + } + } + c=inchar(sc); + if(c==EOF) { + s_return(sc,sc->EOF_OBJ); + } + if(sc->op==OP_PEEK_CHAR) { + backchar(sc,c); + } + s_return(sc,mk_character(sc,c)); + } + + case OP_CHAR_READY: /* char-ready? */ { + pointer p=sc->inport; + int res; + if(is_pair(sc->args)) { + p=car(sc->args); + } + res=p->_object._port->kind&port_string; + s_retbool(res); + } + + case OP_SET_INPORT: /* set-input-port */ + sc->inport=car(sc->args); + s_return(sc,sc->value); + + case OP_SET_OUTPORT: /* set-output-port */ + sc->outport=car(sc->args); + s_return(sc,sc->value); + + case OP_RDSEXPR: + switch (sc->tok) { + case TOK_EOF: + s_return(sc,sc->EOF_OBJ); + /* NOTREACHED */ +/* + * Commented out because we now skip comments in the scanner + * + case TOK_COMMENT: { + int c; + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + } +*/ + case TOK_VEC: + s_save(sc,OP_RDVEC,sc->NIL,sc->NIL); + /* fall through */ + case TOK_LPAREN: + sc->tok = token(sc); + if (sc->tok == TOK_RPAREN) { + s_return(sc,sc->NIL); + } else if (sc->tok == TOK_DOT) { + Error_0(sc,"syntax error: illegal dot expression"); + } else { + sc->nesting_stack[sc->file_i]++; + s_save(sc,OP_RDLIST, sc->NIL, sc->NIL); + s_goto(sc,OP_RDSEXPR); + } + case TOK_QUOTE: + s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + case TOK_BQUOTE: + sc->tok = token(sc); + if(sc->tok==TOK_VEC) { + s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL); + sc->tok=TOK_LPAREN; + s_goto(sc,OP_RDSEXPR); + } else { + s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL); + } + s_goto(sc,OP_RDSEXPR); + case TOK_COMMA: + s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + case TOK_ATMARK: + s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + case TOK_ATOM: + s_return(sc,mk_atom(sc, readstr_upto(sc, DELIMITERS))); + case TOK_DQUOTE: + x=readstrexp(sc); + if(x==sc->F) { + Error_0(sc,"Error reading string"); + } + setimmutable(x); + s_return(sc,x); + case TOK_SHARP: { + pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1); + if(f==sc->NIL) { + Error_0(sc,"undefined sharp expression"); + } else { + sc->code=cons(sc,slot_value_in_env(f),sc->NIL); + s_goto(sc,OP_EVAL); + } + } + case TOK_SHARP_CONST: + if ((x = mk_sharp_const(sc, readstr_upto(sc, DELIMITERS))) == sc->NIL) { + Error_0(sc,"undefined sharp expression"); + } else { + s_return(sc,x); + } + default: + Error_0(sc,"syntax error: illegal token"); + } + break; + + case OP_RDLIST: { + sc->args = cons(sc, sc->value, sc->args); + sc->tok = token(sc); +/* We now skip comments in the scanner + while (sc->tok == TOK_COMMENT) { + int c; + while ((c=inchar(sc)) != '\n' && c!=EOF) + ; + sc->tok = token(sc); + } +*/ + if (sc->tok == TOK_EOF) + { s_return(sc,sc->EOF_OBJ); } + else if (sc->tok == TOK_RPAREN) { + int c = inchar(sc); + if (c != '\n') + backchar(sc,c); +#if SHOW_ERROR_LINE + else if (sc->load_stack[sc->file_i].kind & port_file) + sc->load_stack[sc->file_i].rep.stdio.curr_line++; +#endif + sc->nesting_stack[sc->file_i]--; + s_return(sc,reverse_in_place(sc, sc->NIL, sc->args)); + } else if (sc->tok == TOK_DOT) { + s_save(sc,OP_RDDOT, sc->args, sc->NIL); + sc->tok = token(sc); + s_goto(sc,OP_RDSEXPR); + } else { + s_save(sc,OP_RDLIST, sc->args, sc->NIL);; + s_goto(sc,OP_RDSEXPR); + } + } + + case OP_RDDOT: + if (token(sc) != TOK_RPAREN) { + Error_0(sc,"syntax error: illegal dot expression"); + } else { + sc->nesting_stack[sc->file_i]--; + s_return(sc,reverse_in_place(sc, sc->value, sc->args)); + } + + case OP_RDQUOTE: + s_return(sc,cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL))); + + case OP_RDQQUOTE: + s_return(sc,cons(sc, sc->QQUOTE, cons(sc, sc->value, sc->NIL))); + + case OP_RDQQUOTEVEC: + s_return(sc,cons(sc, mk_symbol(sc,"apply"), + cons(sc, mk_symbol(sc,"vector"), + cons(sc,cons(sc, sc->QQUOTE, + cons(sc,sc->value,sc->NIL)), + sc->NIL)))); + + case OP_RDUNQUOTE: + s_return(sc,cons(sc, sc->UNQUOTE, cons(sc, sc->value, sc->NIL))); + + case OP_RDUQTSP: + s_return(sc,cons(sc, sc->UNQUOTESP, cons(sc, sc->value, sc->NIL))); + + case OP_RDVEC: + /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value); + s_goto(sc,OP_EVAL); Cannot be quoted*/ + /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value); + s_return(sc,x); Cannot be part of pairs*/ + /*sc->code=mk_proc(sc,OP_VECTOR); + sc->args=sc->value; + s_goto(sc,OP_APPLY);*/ + sc->args=sc->value; + s_goto(sc,OP_VECTOR); + + /* ========== printing part ========== */ + case OP_P0LIST: + if(is_vector(sc->args)) { + putstr(sc,"#("); + sc->args=cons(sc,sc->args,mk_integer(sc,0)); + s_goto(sc,OP_PVECFROM); + } else if(is_environment(sc->args)) { + putstr(sc,"#"); + s_return(sc,sc->T); + } else if (!is_pair(sc->args)) { + printatom(sc, sc->args, sc->print_flag); + s_return(sc,sc->T); + } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) { + putstr(sc, "'"); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) { + putstr(sc, "`"); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) { + putstr(sc, ","); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) { + putstr(sc, ",@"); + sc->args = cadr(sc->args); + s_goto(sc,OP_P0LIST); + } else { + putstr(sc, "("); + s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL); + sc->args = car(sc->args); + s_goto(sc,OP_P0LIST); + } + + case OP_P1LIST: + if (is_pair(sc->args)) { + s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL); + putstr(sc, " "); + sc->args = car(sc->args); + s_goto(sc,OP_P0LIST); + } else if(is_vector(sc->args)) { + s_save(sc,OP_P1LIST,sc->NIL,sc->NIL); + putstr(sc, " . "); + s_goto(sc,OP_P0LIST); + } else { + if (sc->args != sc->NIL) { + putstr(sc, " . "); + printatom(sc, sc->args, sc->print_flag); + } + putstr(sc, ")"); + s_return(sc,sc->T); + } + case OP_PVECFROM: { + int i=ivalue_unchecked(cdr(sc->args)); + pointer vec=car(sc->args); + int len=ivalue_unchecked(vec); + if(i==len) { + putstr(sc,")"); + s_return(sc,sc->T); + } else { + pointer elem=vector_elem(vec,i); + ivalue_unchecked(cdr(sc->args))=i+1; + s_save(sc,OP_PVECFROM, sc->args, sc->NIL); + sc->args=elem; + if (i > 0) + putstr(sc," "); + s_goto(sc,OP_P0LIST); + } + } + +#include "../bootstrap-ops-5.c" + + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + + } + return sc->T; +} + +static pointer opexe_6(scheme *sc, enum scheme_opcodes op) { + pointer x, y; + long v; + + switch (op) { + case OP_LIST_LENGTH: /* length */ /* a.k */ + v=list_length(sc,car(sc->args)); + if(v<0) { + Error_1(sc,"length: not a list:",car(sc->args)); + } + s_return(sc,mk_integer(sc, v)); + + case OP_ASSQ: /* assq */ /* a.k */ + x = car(sc->args); + for (y = cadr(sc->args); is_pair(y); y = cdr(y)) { + if (!is_pair(car(y))) { + Error_0(sc,"unable to handle non pair element"); + } + if (x == caar(y)) + break; + } + if (is_pair(y)) { + s_return(sc,car(y)); + } else { + s_return(sc,sc->F); + } + + + case OP_GET_CLOSURE: /* get-closure-code */ /* a.k */ + sc->args = car(sc->args); + if (sc->args == sc->NIL) { + s_return(sc,sc->F); + } else if (is_closure(sc->args)) { + s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value))); + } else if (is_macro(sc->args)) { + s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value))); + } else { + s_return(sc,sc->F); + } + case OP_CLOSUREP: /* closure? */ + /* + * Note, macro object is also a closure. + * Therefore, (closure? <#MACRO>) ==> #t + */ + s_retbool(is_closure(car(sc->args))); + case OP_MACROP: /* macro? */ + s_retbool(is_macro(car(sc->args))); + default: + snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op); + Error_0(sc,sc->strbuff); + } + return sc->T; /* NOTREACHED */ +} + +typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes); + +typedef int (*test_predicate)(pointer); +static int is_any(pointer p) { return 1;} + +static int is_nonneg(pointer p) { + return ivalue(p)>=0 && is_integer(p); +} + +/* Correspond carefully with following defines! */ +static struct { + test_predicate fct; + const char *kind; +} tests[]={ + {0,0}, /* unused */ + {is_any, 0}, + {is_string, "string"}, + {is_symbol, "symbol"}, + {is_port, "port"}, + {is_inport,"input port"}, + {is_outport,"output port"}, + {is_environment, "environment"}, + {is_pair, "pair"}, + {0, "pair or '()"}, + {is_character, "character"}, + {is_vector, "vector"}, + {is_number, "number"}, + {is_integer, "integer"}, + {is_nonneg, "non-negative integer"} +}; + +#define TST_NONE 0 +#define TST_ANY "\001" +#define TST_STRING "\002" +#define TST_SYMBOL "\003" +#define TST_PORT "\004" +#define TST_INPORT "\005" +#define TST_OUTPORT "\006" +#define TST_ENVIRONMENT "\007" +#define TST_PAIR "\010" +#define TST_LIST "\011" +#define TST_CHAR "\012" +#define TST_VECTOR "\013" +#define TST_NUMBER "\014" +#define TST_INTEGER "\015" +#define TST_NATURAL "\016" + +typedef struct { + dispatch_func func; + char *name; + int min_arity; + int max_arity; + char *arg_tests_encoding; +} op_code_info; + +#define INF_ARG 0xffff + +static op_code_info dispatch_table[]= { +#define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E}, +#include "opdefines.h" + { 0 } +}; + +static const char *procname(pointer x) { + int n=procnum(x); + const char *name=dispatch_table[n].name; + if(name==0) { + name="ILLEGAL!"; + } + return name; +} + +/* kernel of this interpreter */ +static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) { + sc->op = op; + for (;;) { + ++Eval_Cycle_Count; + /* if (Eval_Cycle_Count >= 201600) { */ + /* debug = 1; */ + /* } */ + /* if (debug && (Eval_Cycle_Count % 1 == 0)) { */ + /* fprintf(stderr,"[DEBUG] Eval_Cycle_Count=%lld\n",Eval_Cycle_Count); */ + /* } */ + op_code_info *pcd=dispatch_table+sc->op; + if (pcd->name!=0) { /* if built-in function, check arguments */ + char msg[STRBUFFSIZE]; + int ok=1; + int n; + if (debug) { fprintf(stderr,"[DEBUG] built-in [%s]\n",pcd->name); } + n=list_length(sc,sc->args); + + /* Check number of arguments */ + if(nmin_arity) { + ok=0; + snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)", + pcd->name, + pcd->min_arity==pcd->max_arity?"":" at least", + pcd->min_arity); + } + if(ok && n>pcd->max_arity) { + ok=0; + snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)", + pcd->name, + pcd->min_arity==pcd->max_arity?"":" at most", + pcd->max_arity); + } + if(ok) { + if(pcd->arg_tests_encoding!=0) { + int i=0; + int j; + const char *t=pcd->arg_tests_encoding; + pointer arglist=sc->args; + do { + pointer arg=car(arglist); + j=(int)t[0]; + if(j==TST_LIST[0]) { + if(arg!=sc->NIL && !is_pair(arg)) break; + } else { + if(!tests[j].fct(arg)) break; + } + + if(t[1]!=0) {/* last test is replicated as necessary */ + t++; + } + arglist=cdr(arglist); + i++; + } while(iname, + i+1, + tests[j].kind); + } + } + } + if(!ok) { + if(_Error_1(sc,msg,0)==sc->NIL) { + return; + } + pcd=dispatch_table+sc->op; + } + } + if (debug) { fprintf(stderr,"[DEBUG] ok_to_freely_gc\n"); } + ok_to_freely_gc(sc); + if (debug) { fprintf(stderr,"[DEBUG] dispatch sc->op=%d\n",(int)sc->op); } + if (pcd->func(sc, (enum scheme_opcodes)sc->op) == sc->NIL) { + return; + } + if(sc->no_memory) { + fprintf(stderr,"No memory!\n"); + exit(0xe); + return; + } + } +} + +/* ========== Initialization of internal keywords ========== */ + +static void assign_syntax(scheme *sc, char *name) { + pointer x; + + x = oblist_add_by_name(sc, name); + typeflag(x) |= T_SYNTAX; +} + +static void assign_proc(scheme *sc, enum scheme_opcodes op, char *name) { + pointer x, y; + + x = mk_symbol(sc, name); + y = mk_proc(sc,op); + new_slot_in_env(sc, x, y); +} + +static pointer mk_proc(scheme *sc, enum scheme_opcodes op) { + pointer y; + + y = get_cell(sc, sc->NIL, sc->NIL); + typeflag(y) = (T_PROC | T_ATOM); + ivalue_unchecked(y) = (long) op; + set_num_integer(y); + return y; +} + +/* Hard-coded for the given keywords. Remember to rewrite if more are added! */ +static int syntaxnum(pointer p) { + const char *s=strvalue(car(p)); + switch(strlength(car(p))) { + case 2: + if(s[0]=='i') return OP_IF0; /* if */ + else return OP_OR0; /* or */ + case 3: + if(s[0]=='a') return OP_AND0; /* and */ + else return OP_LET0; /* let */ + case 4: + switch(s[3]) { + case 'e': return OP_CASE0; /* case */ + case 'd': return OP_COND0; /* cond */ + case '*': return OP_LET0AST; /* let* */ + default: return OP_SET0; /* set! */ + } + case 5: + switch(s[2]) { + case 'g': return OP_BEGIN; /* begin */ + case 'l': return OP_DELAY; /* delay */ + case 'c': return OP_MACRO0; /* macro */ + default: return OP_QUOTE; /* quote */ + } + case 6: + switch(s[2]) { + case 'm': return OP_LAMBDA; /* lambda */ + case 'f': return OP_DEF0; /* define */ + default: return OP_LET0REC; /* letrec */ + } + default: + return OP_C0STREAM; /* cons-stream */ + } +} + +/* initialization of TinyScheme */ +#if USE_INTERFACE +INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) { + return cons(sc,a,b); +} +INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) { + return immutable_cons(sc,a,b); +} + +static struct scheme_interface vtbl ={ + scheme_define, + s_cons, + s_immutable_cons, + reserve_cells, + mk_integer, + mk_real, + mk_symbol, + gensym, + mk_string, + mk_counted_string, + mk_character, + mk_vector, + mk_foreign_func, + putstr, + putcharacter, + + is_string, + string_value, + is_number, + nvalue, + ivalue, + rvalue, + is_integer, + is_real, + is_character, + charvalue, + is_list, + is_vector, + list_length, + ivalue, + fill_vector, + vector_elem, + set_vector_elem, + is_port, + is_pair, + pair_car, + pair_cdr, + set_car, + set_cdr, + + is_symbol, + symname, + + is_syntax, + is_proc, + is_foreign, + syntaxname, + is_closure, + is_macro, + closure_code, + closure_env, + + is_continuation, + is_promise, + is_environment, + is_immutable, + setimmutable, + + scheme_load_file, + scheme_load_string +}; +#endif + +scheme *scheme_init_new() { + scheme *sc=(scheme*)malloc(sizeof(scheme)); + if(!scheme_init(sc)) { + free(sc); + return 0; + } else { + return sc; + } +} + +scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) { + scheme *sc=(scheme*)malloc(sizeof(scheme)); + if(!scheme_init_custom_alloc(sc,malloc,free)) { + free(sc); + return 0; + } else { + return sc; + } +} + + +int scheme_init(scheme *sc) { + return scheme_init_custom_alloc(sc,malloc,free); +} + +int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) { + int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]); + pointer x; + + num_zero.is_fixnum=1; + num_zero.value.ivalue=0; + num_one.is_fixnum=1; + num_one.value.ivalue=1; + +#if USE_INTERFACE + sc->vptr=&vtbl; +#endif + sc->gensym_cnt=0; + sc->malloc=malloc; + sc->free=free; + sc->last_cell_seg = -1; + sc->sink = &sc->_sink; + sc->NIL = &sc->_NIL; + sc->T = &sc->_HASHT; + sc->F = &sc->_HASHF; + sc->EOF_OBJ=&sc->_EOF_OBJ; + sc->free_cell = &sc->_NIL; + sc->fcells = 0; + sc->no_memory=0; + sc->inport=sc->NIL; + sc->outport=sc->NIL; + sc->save_inport=sc->NIL; + sc->loadport=sc->NIL; + sc->nesting=0; + sc->interactive_repl=0; + + if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) { + sc->no_memory=1; + return 0; + } + sc->gc_verbose = 0; + dump_stack_initialize(sc); + sc->code = sc->NIL; + sc->tracing=0; + + /* init sc->NIL */ + typeflag(sc->NIL) = (T_ATOM | MARK); + car(sc->NIL) = cdr(sc->NIL) = sc->NIL; + /* init T */ + typeflag(sc->T) = (T_ATOM | MARK); + car(sc->T) = cdr(sc->T) = sc->T; + /* init F */ + typeflag(sc->F) = (T_ATOM | MARK); + car(sc->F) = cdr(sc->F) = sc->F; + /* init EOF_OBJ */ + typeflag(sc->EOF_OBJ) = (T_ATOM | MARK); + car(sc->EOF_OBJ) = cdr(sc->EOF_OBJ) = sc->EOF_OBJ; + /* init sink */ + typeflag(sc->sink) = (T_PAIR | MARK); + car(sc->sink) = sc->NIL; + /* init c_nest */ + sc->c_nest = sc->NIL; + + sc->oblist = oblist_initial_value(sc); + /* init global_env */ + new_frame_in_env(sc, sc->NIL); + sc->global_env = sc->envir; + /* init else */ + x = mk_symbol(sc,"else"); + new_slot_in_env(sc, x, sc->T); + + assign_syntax(sc, "lambda"); + assign_syntax(sc, "quote"); + assign_syntax(sc, "define"); + assign_syntax(sc, "if"); + assign_syntax(sc, "begin"); + assign_syntax(sc, "set!"); + assign_syntax(sc, "let"); + assign_syntax(sc, "let*"); + assign_syntax(sc, "letrec"); + assign_syntax(sc, "cond"); + assign_syntax(sc, "delay"); + assign_syntax(sc, "and"); + assign_syntax(sc, "or"); + assign_syntax(sc, "cons-stream"); + assign_syntax(sc, "macro"); + assign_syntax(sc, "case"); + + for(i=0; iLAMBDA = mk_symbol(sc, "lambda"); + sc->QUOTE = mk_symbol(sc, "quote"); + sc->QQUOTE = mk_symbol(sc, "quasiquote"); + sc->UNQUOTE = mk_symbol(sc, "unquote"); + sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing"); + sc->FEED_TO = mk_symbol(sc, "=>"); + sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*"); + sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*"); + sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*"); + sc->COMPILE_HOOK = mk_symbol(sc, "*compile-hook*"); + + return !sc->no_memory; +} + +void scheme_set_input_port_file(scheme *sc, FILE *fin) { + sc->inport=port_from_file(sc,fin,port_input); +} + +void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) { + sc->inport=port_from_string(sc,start,past_the_end,port_input); +} + +void scheme_set_output_port_file(scheme *sc, FILE *fout) { + sc->outport=port_from_file(sc,fout,port_output); +} + +void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) { + sc->outport=port_from_string(sc,start,past_the_end,port_output); +} + +void scheme_set_external_data(scheme *sc, void *p) { + sc->ext_data=p; +} + +void scheme_deinit(scheme *sc) { + int i; + +#if SHOW_ERROR_LINE + char *fname; +#endif + + sc->oblist=sc->NIL; + sc->global_env=sc->NIL; + dump_stack_free(sc); + sc->envir=sc->NIL; + sc->code=sc->NIL; + sc->args=sc->NIL; + sc->value=sc->NIL; + if(is_port(sc->inport)) { + typeflag(sc->inport) = T_ATOM; + } + sc->inport=sc->NIL; + sc->outport=sc->NIL; + if(is_port(sc->save_inport)) { + typeflag(sc->save_inport) = T_ATOM; + } + sc->save_inport=sc->NIL; + if(is_port(sc->loadport)) { + typeflag(sc->loadport) = T_ATOM; + } + sc->loadport=sc->NIL; + sc->gc_verbose=0; + gc(sc,sc->NIL,sc->NIL); + + for(i=0; i<=sc->last_cell_seg; i++) { + sc->free(sc->alloc_seg[i]); + } + +#if SHOW_ERROR_LINE + for(i=0; i<=sc->file_i; i++) { + if (sc->load_stack[i].kind & port_file) { + fname = sc->load_stack[i].rep.stdio.filename; + if(fname) + sc->free(fname); + } + } +#endif +} + +void scheme_load_file(scheme *sc, FILE *fin) +{ scheme_load_named_file(sc,fin,0); } + +void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename) { + dump_stack_reset(sc); + sc->envir = sc->global_env; + sc->file_i=0; + sc->load_stack[0].kind=port_input|port_file; + sc->load_stack[0].rep.stdio.file=fin; + sc->loadport=mk_port(sc,sc->load_stack); + sc->retcode=0; + if(fin==stdin) { + sc->interactive_repl=1; + } + +#if SHOW_ERROR_LINE + sc->load_stack[0].rep.stdio.curr_line = 0; + if(fin!=stdin && filename) + sc->load_stack[0].rep.stdio.filename = store_string(sc, strlen(filename), filename, 0); +#endif + + sc->inport=sc->loadport; + sc->args = mk_integer(sc,sc->file_i); + Eval_Cycle(sc, OP_T0LVL); + typeflag(sc->loadport)=T_ATOM; + if(sc->retcode==0) { + sc->retcode=sc->nesting!=0; + } +} + +void scheme_load_string(scheme *sc, const char *cmd) { + dump_stack_reset(sc); + sc->envir = sc->global_env; + sc->file_i=0; + sc->load_stack[0].kind=port_input|port_string; + sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */ + sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd); + sc->load_stack[0].rep.string.curr=(char*)cmd; + sc->loadport=mk_port(sc,sc->load_stack); + sc->retcode=0; + sc->interactive_repl=0; + sc->inport=sc->loadport; + sc->args = mk_integer(sc,sc->file_i); + Eval_Cycle(sc, OP_T0LVL); + typeflag(sc->loadport)=T_ATOM; + if(sc->retcode==0) { + sc->retcode=sc->nesting!=0; + } +} + +void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) { + pointer x; + + x=find_slot_in_env(sc,envir,symbol,0); + if (x != sc->NIL) { + set_slot_in_env(sc, x, value); + } else { + new_slot_spec_in_env(sc, envir, symbol, value); + } +} + +#if !STANDALONE +void scheme_register_foreign_func(scheme * sc, scheme_registerable * sr) +{ + scheme_define(sc, + sc->global_env, + mk_symbol(sc,sr->name), + mk_foreign_func(sc, sr->f)); +} + +void scheme_register_foreign_func_list(scheme * sc, + scheme_registerable * list, + int count) +{ + int i; + for(i = 0; i < count; i++) + { + scheme_register_foreign_func(sc, list + i); + } +} + +pointer scheme_apply0(scheme *sc, const char *procname) +{ return scheme_eval(sc, cons(sc,mk_symbol(sc,procname),sc->NIL)); } + +void save_from_C_call(scheme *sc) +{ + pointer saved_data = + cons(sc, + car(sc->sink), + cons(sc, + sc->envir, + sc->dump)); + /* Push */ + sc->c_nest = cons(sc, saved_data, sc->c_nest); + /* Truncate the dump stack so TS will return here when done, not + directly resume pre-C-call operations. */ + dump_stack_reset(sc); +} +void restore_from_C_call(scheme *sc) +{ + car(sc->sink) = caar(sc->c_nest); + sc->envir = cadar(sc->c_nest); + sc->dump = cdr(cdar(sc->c_nest)); + /* Pop */ + sc->c_nest = cdr(sc->c_nest); +} + +/* "func" and "args" are assumed to be already eval'ed. */ +pointer scheme_call(scheme *sc, pointer func, pointer args) +{ + int old_repl = sc->interactive_repl; + sc->interactive_repl = 0; + save_from_C_call(sc); + sc->envir = sc->global_env; + sc->args = args; + sc->code = func; + sc->retcode = 0; + Eval_Cycle(sc, OP_APPLY); + sc->interactive_repl = old_repl; + restore_from_C_call(sc); + return sc->value; +} + +pointer scheme_eval(scheme *sc, pointer obj) +{ + int old_repl = sc->interactive_repl; + sc->interactive_repl = 0; + save_from_C_call(sc); + sc->args = sc->NIL; + sc->code = obj; + sc->retcode = 0; + Eval_Cycle(sc, OP_EVAL); + sc->interactive_repl = old_repl; + restore_from_C_call(sc); + return sc->value; +} + + +#endif + +/* ========== Main ========== */ + +#if STANDALONE + +#if defined(__APPLE__) && !defined (OSX) +int main() +{ + extern MacTS_main(int argc, char **argv); + char** argv; + int argc = ccommand(&argv); + MacTS_main(argc,argv); + return 0; +} +int MacTS_main(int argc, char **argv) { +#else +int main(int argc, char **argv) { +#endif + scheme sc; + FILE *fin = 0; + char *file_name=InitFile; + int retcode; + int isfile=1; + + if(argc==1) { + printf(banner); + } + if(argc==2 && strcmp(argv[1],"-?")==0) { + printf("Usage: tinyscheme -?\n"); + printf("or: tinyscheme [ ...]\n"); + printf("followed by\n"); + printf(" -1 [ ...]\n"); + printf(" -c [ ...]\n"); + printf("assuming that the executable is named tinyscheme.\n"); + printf("Use - as filename for stdin.\n"); + return 1; + } + if(!scheme_init(&sc)) { + fprintf(stderr,"Could not initialize!\n"); + return 2; + } + scheme_set_input_port_file(&sc, stdin); + scheme_set_output_port_file(&sc, stdout); +#if USE_DL + scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext)); +#endif + argv++; + if(access(file_name,0)!=0) { + char *p=getenv("TINYSCHEMEINIT"); + if(p!=0) { + file_name=p; + } + } + do { + if(strcmp(file_name,"-")==0) { + fin=stdin; + } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) { + pointer args=sc.NIL; + isfile=file_name[1]=='1'; + file_name=*argv++; + if(strcmp(file_name,"-")==0) { + fin=stdin; + } else if(isfile) { + fin=fopen(file_name,"r"); + } + for(;*argv;argv++) { + pointer value=mk_string(&sc,*argv); + args=cons(&sc,value,args); + } + args=reverse_in_place(&sc,sc.NIL,args); + scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args); + + } else { + fin=fopen(file_name,"r"); + } + if(isfile && fin==0) { + fprintf(stderr,"Could not open file %s\n",file_name); + } else { + if(isfile) { + scheme_load_named_file(&sc,fin,file_name); + } else { + scheme_load_string(&sc,file_name); + } + if(!isfile || fin!=stdin) { + if(sc.retcode!=0) { + fprintf(stderr,"Errors encountered reading %s\n",file_name); + } + if(isfile) { + fclose(fin); + } + } + } + file_name=*argv++; + } while(file_name!=0); + if(argc==1) { + scheme_load_named_file(&sc,stdin,0); + } + retcode=sc.retcode; + scheme_deinit(&sc); + + return retcode; +} + +#endif + +/* +Local variables: +c-file-style: "k&r" +End: +*/ diff --git a/bootstrap/tinyscheme-1.41/scheme.h b/bootstrap/tinyscheme-1.41/scheme.h new file mode 100644 index 0000000..0789049 --- /dev/null +++ b/bootstrap/tinyscheme-1.41/scheme.h @@ -0,0 +1,255 @@ +/* SCHEME.H */ + +#ifndef _SCHEME_H +#define _SCHEME_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default values for #define'd symbols + */ +#ifndef STANDALONE /* If used as standalone interpreter */ +# define STANDALONE 1 +#endif + +#ifndef _MSC_VER +# define USE_STRCASECMP 1 +# ifndef USE_STRLWR +# define USE_STRLWR 1 +# endif +# define SCHEME_EXPORT +#else +# define USE_STRCASECMP 0 +# define USE_STRLWR 0 +# ifdef _SCHEME_SOURCE +# define SCHEME_EXPORT __declspec(dllexport) +# else +# define SCHEME_EXPORT __declspec(dllimport) +# endif +#endif + +#if USE_NO_FEATURES +# define USE_MATH 0 +# define USE_CHAR_CLASSIFIERS 0 +# define USE_ASCII_NAMES 0 +# define USE_STRING_PORTS 0 +# define USE_ERROR_HOOK 0 +# define USE_TRACING 0 +# define USE_COLON_HOOK 0 +# define USE_DL 0 +# define USE_PLIST 0 +#endif + +/* + * Leave it defined if you want continuations, and also for the Sharp Zaurus. + * Undefine it if you only care about faster speed and not strict Scheme compatibility. + */ +#define USE_SCHEME_STACK + +#if USE_DL +# define USE_INTERFACE 1 +#endif + + +#ifndef USE_MATH /* If math support is needed */ +# define USE_MATH 1 +#endif + +#ifndef USE_CHAR_CLASSIFIERS /* If char classifiers are needed */ +# define USE_CHAR_CLASSIFIERS 1 +#endif + +#ifndef USE_ASCII_NAMES /* If extended escaped characters are needed */ +# define USE_ASCII_NAMES 1 +#endif + +#ifndef USE_STRING_PORTS /* Enable string ports */ +# define USE_STRING_PORTS 1 +#endif + +#ifndef USE_TRACING +# define USE_TRACING 1 +#endif + +#ifndef USE_PLIST +# define USE_PLIST 0 +#endif + +/* To force system errors through user-defined error handling (see *error-hook*) */ +#ifndef USE_ERROR_HOOK +# define USE_ERROR_HOOK 1 +#endif + +#ifndef USE_COLON_HOOK /* Enable qualified qualifier */ +# define USE_COLON_HOOK 1 +#endif + +#ifndef USE_STRCASECMP /* stricmp for Unix */ +# define USE_STRCASECMP 0 +#endif + +#ifndef USE_STRLWR +# define USE_STRLWR 1 +#endif + +#ifndef STDIO_ADDS_CR /* Define if DOS/Windows */ +# define STDIO_ADDS_CR 0 +#endif + +#ifndef INLINE +# define INLINE +#endif + +#ifndef USE_INTERFACE +# define USE_INTERFACE 0 +#endif + +#ifndef SHOW_ERROR_LINE /* Show error line in file */ +# define SHOW_ERROR_LINE 1 +#endif + +typedef struct scheme scheme; +typedef struct cell *pointer; + +typedef void * (*func_alloc)(size_t); +typedef void (*func_dealloc)(void *); + +/* num, for generic arithmetic */ +typedef struct num { + char is_fixnum; + union { + long ivalue; + double rvalue; + } value; +} num; + +SCHEME_EXPORT scheme *scheme_init_new(); +SCHEME_EXPORT scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free); +SCHEME_EXPORT int scheme_init(scheme *sc); +SCHEME_EXPORT int scheme_init_custom_alloc(scheme *sc, func_alloc, func_dealloc); +SCHEME_EXPORT void scheme_deinit(scheme *sc); +void scheme_set_input_port_file(scheme *sc, FILE *fin); +void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end); +SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fin); +void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end); +SCHEME_EXPORT void scheme_load_file(scheme *sc, FILE *fin); +SCHEME_EXPORT void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename); +SCHEME_EXPORT void scheme_load_string(scheme *sc, const char *cmd); +SCHEME_EXPORT pointer scheme_apply0(scheme *sc, const char *procname); +SCHEME_EXPORT pointer scheme_call(scheme *sc, pointer func, pointer args); +SCHEME_EXPORT pointer scheme_eval(scheme *sc, pointer obj); +void scheme_set_external_data(scheme *sc, void *p); +SCHEME_EXPORT void scheme_define(scheme *sc, pointer env, pointer symbol, pointer value); + +typedef pointer (*foreign_func)(scheme *, pointer); + +pointer _cons(scheme *sc, pointer a, pointer b, int immutable); +pointer mk_integer(scheme *sc, long num); +pointer mk_real(scheme *sc, double num); +pointer mk_symbol(scheme *sc, const char *name); +pointer gensym(scheme *sc); +pointer mk_string(scheme *sc, const char *str); +pointer mk_counted_string(scheme *sc, const char *str, int len); +pointer mk_empty_string(scheme *sc, int len, char fill); +pointer mk_character(scheme *sc, int c); +pointer mk_foreign_func(scheme *sc, foreign_func f); +void putstr(scheme *sc, const char *s); +int list_length(scheme *sc, pointer a); +int eqv(pointer a, pointer b); + + +#if USE_INTERFACE +struct scheme_interface { + void (*scheme_define)(scheme *sc, pointer env, pointer symbol, pointer value); + pointer (*cons)(scheme *sc, pointer a, pointer b); + pointer (*immutable_cons)(scheme *sc, pointer a, pointer b); + pointer (*reserve_cells)(scheme *sc, int n); + pointer (*mk_integer)(scheme *sc, long num); + pointer (*mk_real)(scheme *sc, double num); + pointer (*mk_symbol)(scheme *sc, const char *name); + pointer (*gensym)(scheme *sc); + pointer (*mk_string)(scheme *sc, const char *str); + pointer (*mk_counted_string)(scheme *sc, const char *str, int len); + pointer (*mk_character)(scheme *sc, int c); + pointer (*mk_vector)(scheme *sc, int len); + pointer (*mk_foreign_func)(scheme *sc, foreign_func f); + void (*putstr)(scheme *sc, const char *s); + void (*putcharacter)(scheme *sc, int c); + + int (*is_string)(pointer p); + char *(*string_value)(pointer p); + int (*is_number)(pointer p); + num (*nvalue)(pointer p); + long (*ivalue)(pointer p); + double (*rvalue)(pointer p); + int (*is_integer)(pointer p); + int (*is_real)(pointer p); + int (*is_character)(pointer p); + long (*charvalue)(pointer p); + int (*is_list)(scheme *sc, pointer p); + int (*is_vector)(pointer p); + int (*list_length)(scheme *sc, pointer vec); + long (*vector_length)(pointer vec); + void (*fill_vector)(pointer vec, pointer elem); + pointer (*vector_elem)(pointer vec, int ielem); + pointer (*set_vector_elem)(pointer vec, int ielem, pointer newel); + int (*is_port)(pointer p); + + int (*is_pair)(pointer p); + pointer (*pair_car)(pointer p); + pointer (*pair_cdr)(pointer p); + pointer (*set_car)(pointer p, pointer q); + pointer (*set_cdr)(pointer p, pointer q); + + int (*is_symbol)(pointer p); + char *(*symname)(pointer p); + + int (*is_syntax)(pointer p); + int (*is_proc)(pointer p); + int (*is_foreign)(pointer p); + char *(*syntaxname)(pointer p); + int (*is_closure)(pointer p); + int (*is_macro)(pointer p); + pointer (*closure_code)(pointer p); + pointer (*closure_env)(pointer p); + + int (*is_continuation)(pointer p); + int (*is_promise)(pointer p); + int (*is_environment)(pointer p); + int (*is_immutable)(pointer p); + void (*setimmutable)(pointer p); + void (*load_file)(scheme *sc, FILE *fin); + void (*load_string)(scheme *sc, const char *input); +}; +#endif + +#if !STANDALONE +typedef struct scheme_registerable +{ + foreign_func f; + const char * name; +} +scheme_registerable; + +void scheme_register_foreign_func_list(scheme * sc, + scheme_registerable * list, + int n); + +#endif /* !STANDALONE */ + +#ifdef __cplusplus +} +#endif + +#endif + + +/* +Local variables: +c-file-style: "k&r" +End: +*/ diff --git a/readme/Depend.md b/readme/Depend.md new file mode 100644 index 0000000..d30bcbd --- /dev/null +++ b/readme/Depend.md @@ -0,0 +1,74 @@ +# Dependencies + +- gcc, ar +- diff +- GNU make +- NASM +- SPIM + +## Details + +GCC is used to compile the TinyScheme interpreter which is used to +bootstrap the project, which is written in C. A custom version of the +TinyScheme interpreter source is included as part of this +codebase. TinyScheme was set up for many platforms/compilers so it +should be fairly easy to replace this with other compilers. + +GCC is also used to compile some minimal runtime library functions +written in C. These pieces may eventually be replaced with +assembly. Again, it should be relatively simple to replace GCC for this purpose. + +NASM is used to assemble x86 code files generated by the backend, +producing object code output (`.o`, `.obj`). The backend produces x86 +assembly code in a format that is somewhat specific to NASM, so it may +be more difficult to replace this component with a different assembler +(e.g. GAS). + +The archiver tool (ar) is used during the build process to group +object code files into lib files. It should be straightforward to +replace this with any appropriate library tool. + +Finally GCC is used as a linker for the object code and lib files to +produce the final exe. It should be straightforward to use other +linker tools for this purpose. + +The project is currently tested and developed on a Windows machine +using the MinGW port of gcc, ar and make. Testing and supporting other +platforms (Linux) and compilers (clang) is planned and/or in progress. + +SPIM is used as a testbed tool for verifying that the MIPS backend is +working, but this is not a required dependency to bootstrap the +compiler on an x86 machine. + +## Tested Dependency Versions on Windows + +The project is tested with these versions of the dependency +components. Replacing these components or picking up new versions may +require some tweaks to the project. + + >ver + Microsoft Windows [Version 10.0.17763.253] + + >make --version + GNU Make 3.82.90 + Built for i686-pc-mingw32 + + >gcc --version + gcc (GCC) 5.3.0 + + >ar --version + GNU ar (GNU Binutils) 2.25.1 + + >diff --version + diff (GNU diffutils) 3.6 + + >nasm -version + NASM version 2.12.02 compiled on Jul 6 2016 + + +See [MinGW](http://mingw.org/) for native Windows builds of the GNU +tools, including make, gcc, and ar, and diff. MSYS is a component of +the Windows port of Git, so also check the usr\bin directory of the +Git install for some tools, including diff. + +See [NASM](https://www.nasm.us/) for The Netwide Assembler. diff --git a/readme/OldReadme.md b/readme/OldReadme.md new file mode 100644 index 0000000..6682734 --- /dev/null +++ b/readme/OldReadme.md @@ -0,0 +1,249 @@ +# Old Readme + +This project started out as a graduate school project at the +University of Washington. The documentation below was converted to +markdown and preserved because it might still be helpful. + +# Compiler Project README + +http://www.cs.washington.edu/homes/rrusso/compiler/ + +# Table of Contents + +1. Unpacking the compiler +2. Running the compiler using the makefile +3. Running the SASM interpreter +4. Running the compiled code +5. Running the test suite + +# 1. Unpacking the compiler + +The project is archived in ZIP format and available for download on my +website. The archive is named with the version, and it will unpack +into a directory that has the same name (i.e. rrusso-project-0.1.zip +unpacks into a directory named rrusso-project-0.1). + +# 2. Running the compiler and using the makefile + +Running the compiler and interpreter takes very little setup. In the +directory where you unpacked the project, there will be a makefile. +This makefile will help automate running several phases of the +compiler. This is an academic project and not a commercial product, +so the phases of the compiler are not wrapped up in a single +commandline shell. But luckily, this makefile will help automate +things. + +The main dependency for running the compiler and interpreter is +mzscheme from the PLT Scheme distribution. That is available for +download from http://www.plt-scheme.org/. If you happen to be another +UW computer science student, you can use the copy that is installed on +Attu. + +With mzscheme in place, you can begin compiling MiniJava programs. +Here's an example: + + > make TwoArgs.asm + mzscheme --script run.scm compiler.scm tests/TwoArgs.java >TwoArgs.sasm + mzscheme --script run.scm sasm-opt.scm TwoArgs.sasm >TwoArgs.sasm-opt + mzscheme --script run.scm sasm.scm TwoArgs.sasm-opt >TwoArgs.asm + +The makefile takes care of running the base compiler, the optimizer, +and then the final translation step that produces x86 assembly. If +you want to run the MIPS version of the compiler, you issue a +different makefile command: + + > make TwoArgs-spim.s + mzscheme --script run.scm sasm-opt-mips.scm TwoArgs.sasm >TwoArgs.sasm-opt-mips + mzscheme --script run.scm sasm-mips.scm TwoArgs.sasm-opt-mips >TwoArgs.s + mzscheme --script run.scm sasm-opt-mips.scm rtl/mjrtl-mips.sasm >mjrtlp.sasm-opt-mips + mzscheme --script run.scm sasm-mips.scm mjrtlp.sasm-opt-mips >mjrtlp-mips.s + mzscheme --script run.scm sasm-opt-mips.scm rtl/heap.sasm >heap-mips.sasm + mzscheme --script run.scm sasm-mips.scm heap-mips.sasm >heap-mips.s + mzscheme --script run.scm sasm-opt-mips.scm rtl/gc.sasm >gc-mips.sasm + mzscheme --script run.scm sasm-mips.scm gc-mips.sasm >gc-mips.s + mzscheme --script run.scm sasm-opt-mips.scm rtl/c-rtlheap.sasm >rtlheap-mips.sasm + mzscheme --script run.scm sasm-mips.scm rtlheap-mips.sasm >rtlheap-mips.s + cat rtl/spim-main.s mjrtlp-mips.s heap-mips.s gc-mips.s rtlheap-mips.s TwoArgs.s >TwoArgs-spim.s + +Notice that a lot more commands get run. All this extra work is +because the runtime library (heap management and GC) is being +translated into MIPS assembly, and inlined right there to form a +final, standalone MIPS assembly source file you can run inside SPIM. + +I've been using "TwoArgs" as an example here, but it is just one test +from the "tests" directory. If you look in that directory you will +notice several test input programs. You can compile any of these; +just substitute the name for TwoArgs in the commands above. Some of +these programs come from the original MiniJava project website, +because I used them as test programs in my original project for +CSEP501. + +You can choose to run only a particular phase of the compiler, by +issuing a different make command. For instance, suppose you want to +run just the optimizer and you don't want to generate X86 assembly. +In that case you can run this command: + + > make TwoArgs.sasm-opt + mzscheme --script run.scm compiler.scm tests/TwoArgs.java >TwoArgs.sasm + mzscheme --script run.scm sasm-opt.scm TwoArgs.sasm >TwoArgs.sasm-opt + +If all of the intermediate files are making a mess in the directory, +you can run a clean command: + + > make clean + + +# 3. Running the SASM interpreter + +The SASM interpreter is very simple to run and introduces no +additional dependencies other than the one needed to run the basic +compiler (make and mzscheme). + +To run the compiler, use the ".actual" makefile rule. The name is +intended to represent "actual program output" as opposed to the output +generated by the program when compiled by a known-good Java compiler. + +Here is an example using the old TwoArgs example: + + > make TwoArgs.actual + mzscheme --script run.scm compiler.scm tests/TwoArgs.java >TwoArgs.sasm + mzscheme --script run.scm sasm-interp.scm rtl/heap.sasm rtl/gc.sasm rtl/rtlheap.sasm TwoArgs.sasm >TwoArgs.actual + +Notice that the optimization phase is not run. It is possible to run +the interpreter on optimized code; in fact this is something I +definitely took advantage of to help verify my optimizer before +generating native code. But by default this makefile rule just runs +the SASM interpreter against the unoptimized SASM output. + +You can use this same command for any program in the "tests" +directory, just substitute the name in the above command. + +Notice that the interpreter is executed with 4 actual input files: +heap.sasm, gc.sasm, rtlheap.sasm, and finally the actual input program +to interpret. The other three SASM programs are the runtime library +that implement heap management and GC. The SASM interpreter can +operate in a very high-level symbolic mode, or it can operate in a +lower-level machine mode so that low-level programs like the heap +manager and GC can run. + +# 4. Running the compiled code == + +## Running X86 Code + +Running the compiled X86 code may be something of a pain because of +all of the dependencies required. But if you have them, the makefile +should help you automate this process completely. + +First off, the only platform on which running the X86 code was tested +is a Cygwin environment running on a 32-bit version of Windows XP. In +that environment, GCC v3.4.4 was used to compile C code and link +object files, and NASM v0.98.39 was used to assemble the output code +of my compiler. It should be very possible to run the code on other +platforms but it hasn't been tested and likely will hit a snag here or +there during compilation/linking. + +Cygwin is available for download at: http://www.cygwin.com/. +NASM is available at: http://sourceforge.net/projects/nasm/. + +If you have all of the right dependencies, you should be able to run +the X86 code with a simple makefile command: + + > make TwoArgs.native-actual + mzscheme --script compiler.scm tests/TwoArgs.java >TwoArgs.sasm + mzscheme --script sasm-opt.scm TwoArgs.sasm >TwoArgs.sasm-opt + mzscheme --script sasm.scm TwoArgs.sasm-opt >TwoArgs.asm + mzscheme --script sasm-opt.scm rtl/heap.sasm >heap-x86.sasm + mzscheme --script sasm.scm heap-x86.sasm >heap-x86.asm + nasmw -fwin32 heap-x86.asm + mzscheme --script sasm-opt.scm rtl/gc.sasm >gc-x86.sasm + mzscheme --script sasm.scm gc-x86.sasm >gc-x86.asm + nasmw -fwin32 gc-x86.asm + mzscheme --script sasm-opt.scm rtl/c-rtlheap.sasm >rtlheap-x86.sasm + mzscheme --script sasm.scm rtlheap-x86.sasm >rtlheap-x86.asm + nasmw -fwin32 rtlheap-x86.asm + mzscheme --script sasm-opt.scm rtl/mjrtl.sasm >mjrtlp.sasm-opt + mzscheme --script sasm.scm mjrtlp.sasm-opt >mjrtlp.asm + nasmw -fwin32 mjrtlp.asm + nasmw -fwin32 TwoArgs.asm + gcc rtl/mjrtl.c TwoArgs.obj heap-x86.obj gc-x86.obj rtlheap-x86.obj mjrtlp.obj + ./a.exe >TwoArgs.native-actual + +The ".native-actual" rule is getting a bit long, but stands for +"actual program output, generated by native code". Actual output as +opposed to output generated by the program when compiled by a +known-good Java compiler; native as opposed to running under the SASM +interpreter. + +Once again this looks like a lot of commands, but it shows the +makefile automatically compiling and assembling the heap management +and GC routines for the runtime library. Usually this only needs to +be done once and then you can compile and run other X86 code without +redoing all of that work. + +## Running the MIPS Code + +Running the MIPS code is much easier because it has far fewer +dependencies. Namely, you'll just need PC SPIM. You can get PC SPIM +from James Larus' website: + +http://www.cs.wisc.edu/~larus/spim.html + +PC SPIM is small to download and simple to install. If you wanted to +try out my project and don't want to spend a lot of time setting up +cygwin, GCC and NASM, this is probably your best bet. + +I've only tested my MIPS output running on PC SPIM with the default +settings. There are other builds of SPIM there and lots of options +that you can use to configure SPIMs runtime behavior. While it should +be possible to get the code running in any situation, just be warned +that only that configuration is tested. + +The steps above in section 2 demonstrate how to build a "*-spim.s" +file. This assembly source file is a completely self-contained +program that you can feed into SPIM. It includes all of the compiled +MIPS code from the original MiniJava source program, plus the whole +runtime library inlined. + +You should be able to simply load up that "*-spim.s" file in SPIM and +press the "go" button (F5 is the hotkey in the build I am using). The +"System.out.println" statements in the MiniJava program should be +reflected in the Console window of PC SPIM. They will be prefixed +with "@SYSTEM-OUT-PRINTLN". You can use the "fix-spimout.scm" program +to strip out these lines from stdin and produce a clean output file on +stdout that you can diff against the expected output. I did it this +way because I couldn't get SPIM to leave out any header lines and just +print my output. So instead I went with this prefix/cleanup solution +to help automate things. + +# 5. Running the test suite + +Running the test suite again has only been tested on the WinXP/Cygwin +platform. It adds an additional requirement, which is GCJ, or the GNU +Compiler for Java. GCJ is a native code compiler for Java. Like the +rest of GCC, it is available for installation through Cygwin so if you +already have that, it's the easiest way to get it. + +After you get GCJ installed, you can just run a few simple makefile +rules to test the output of the interpreter, or actual compiled X86 +code. Use this example to diff the interpreter against the output of +GCC: + + > make TwoArgs.test + mzscheme --script sasm-interp.scm rtl/heap.sasm rtl/gc.sasm rtl/rtlheap.sasm TwoArgs.sasm >TwoArgs.actual + diff TwoArgs.out TwoArgs.actual >TwoArgs.test + +This example uses the "*.test" rule. You can use it for any program +in the "tests" directory. If the output files match, diff will return +a 0 status code and the make operation will succeed. If the files do +not match, diff returns a nonzero code and the make operation fails. + +This example will allow you to diff the GCJ output against the output +of the program as compiled by my X86 compiler: + + > make TwoArgs.ntest + gcj --main=TwoArgs tests/TwoArgs.java + ./a.exe >TwoArgs.out + diff TwoArgs.out TwoArgs.native-actual >TwoArgs.ntest + +The rule to use in this case is "*.ntest", for "native test". + diff --git a/readme/SASM.md b/readme/SASM.md new file mode 100644 index 0000000..ac044d1 --- /dev/null +++ b/readme/SASM.md @@ -0,0 +1,46 @@ +# Symbolic Assembly Language + +SASM is an abstract assembly language. The operations performed and +the registers and other storage manipulated by those operations are +all represented symbolically. + +# Example + +Consider the following example instruction: + + (assign (reg operand) (op load-array) (label $scmglobal-char-Eq?) (const 0)) + +This is an assignment instruction. The target of the assignment +(left-hand side) is an abstract register, named `operand`. The source +of the assignment (right-hand side) is an operation, named +`load-array` which references memory. A label is used for the base +pointer of the load-array operation, and a 0-word offset is specified. + +This is an exact instruction emitted by the Scheme frontend for +referencing a global variable. When we run this instruction through +the SASM "optimizer" tool, sasm-opt.exe, it is translated into a more +specific form of SASM instruction: + + (assign (reg ebx) (op load-array) (label $scmglobal-char-Eq?) (const 0)) + +In this form of the instruction, the symbolic `operand` register is +replaced with a real, physical x86 register `ebx`. The remainder of +the instruction is still exactly the same. In this case, there is a +static mapping of the operand register to ebx, however the +sasm-opt.exe tool is capable of performing register allocation and +transforming other storage such as `(temp my-variable)` and `(local +1)` into actual register references. + +Lastly, we run this instruction through the sasm.exe tool, and it is +translated into an actual x86 instruction that is recognized by NASM. + + mov ebx, [___Doscmglobal_char_Eq__Qu] + + +# Notes + +The base syntax for SASM is a Scheme or LISP style s-exp, although +supporting other syntaxes is planned work. + +The SASM language was heavily influenced by Wizard Book's [5th chapter](https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-30.html#%_chap_5), +Computing With Register Machines. diff --git a/readme/Status.md b/readme/Status.md new file mode 100644 index 0000000..664ac43 --- /dev/null +++ b/readme/Status.md @@ -0,0 +1,73 @@ +# Project Status + +The compiler platform is currently able to bootstrap on top of an +interpreter, and the result of the bootstrap process is able to +compile itself. + +The backend is capable of generating x86 and MIPS assembly source, a +separate tool is used to assemble that source to object code. + +## Implementation Language Choice + +The project started out in R5RS Scheme, in large part due to +inspiration from Wizard Book, and the author was determined to +bootstrap the compiler in that language. Scheme is a useful +programming language but has a very small community by modern +standards, which might limit the overall interest in the project. + +The plan is to adapt more of the components of the project over to a +more mainstream language, however keep the Scheme frontend of the +compiler written in Scheme. JavaScript seems like an ideal choice +given many language similarities with respect to Scheme and the +amazing community and tools that have been built up around JavaScript +over the years. + +## R5RS Scheme Implementation + +The Scheme implementation provided by the compiler and associated +runtime library is not trivial, however it does not provide a complete +implementation of R5RS. Notably it is lacking a number tower and +support for continuations. + +Continuation support was planned and there is a continuation-passing +style transform module partially implemented in the compiler. However +this was not necessary for bootstrap so left for a later project. + +Similarly the number tower work was not necessary for bootstrap and +left for a later project. + +The Scheme frontend is fairly simplistic, and a lot of work needs to +be done to make the output of the Scheme frontend more efficient. In +particular, eliminating environment allocation would be a big +improvement. In general, many of the ideas of the Rabbit scheme +compiler were planned to be implemented but are not done for the +initial release. + +## Runtime Library + +The memory management heap implementation needs some work to allow the +heap to grow and shrink. Currently it can be configured at compile +time to be large or small depending on the expected working set size. + +The garbage collector is conservative and very simple, it uses a +mark-and-sweep algorithm. Pointer reversal was planned but not yet +implemented. Pointer reversal is needed to make the system reliable, +when working on large working sets it is not hard to blow the stack +and crash the executables during GC. + +The Scheme runtime library needs various improvements, for example it +should support some bit twiddling to distinguish integers from +pointers at runtime, so that not all integers need to be boxed as +objects. Another planned improvement is to represent Scheme objects in +the same format as that expected by the Java frontend so some runtime +library code may be reused and shared. + +## Tools + +The phases of the compiler are all separate tools, currently these +phases are not wrapped up into a convenient command-line tool +("driver" is the archaic term among compiler developers for such a +tool such as cl.exe). So one has to script the phases of the compiler +by hand which is a nuisance. A more convenient tool wrapping the +phases was planned but not required for bootstrap. + diff --git a/readme/Tools.md b/readme/Tools.md new file mode 100644 index 0000000..4dad91e --- /dev/null +++ b/readme/Tools.md @@ -0,0 +1,39 @@ +# Tools + +## schemec.exe + +This is the compiler frontend for a useful subset of R5RS Scheme. It supports a dialect of Scheme named "conspiracy" which includes (need x/y/z) syntax for separate compilation and dependency tracking. + +The output of schemec is a SASM program (.scm to .sasm) and a separate syntax file (.sasm-syntax) which is used in separate compilation of `define-syntax` and `syntax-rules`. + +## sasm-opt.exe + +This is the SASM "optimizer" tool which can perform dataflow analysis, instruction elimination, register allocation, and so on. It takes a .sasm file and translates it into a .sasm-opt file. + +The sasm-opt.exe tool is responsible for code improvements and also specializing the SASM input into a less abstract form, referencing actual registers instead of abstract register names for the target, and rewriting the original SASM input into a form that is compatible with the target. + +It can run in a `--cheap` mode where it performs minimal transformation on the input to save time if the input meets some requirements. The `--cheap` mode is compatible with the output from the Scheme frontend to make bootstrap faster. + +The sasm-opt.exe tool is specialized for the x86 backend. A separate tool, sasm-opt-mips, is generated for targeting MIPS. + +## sasm.exe + +The sasm.exe tool translates the output of sasm-opt.exe into a x86 .asm file for NASM. Similar to the case with sasm-opt.exe, there is a separate tool for the MIPS backend. + +# Example + + REM + set RTL_OBJS=out/bootstrap/c-rtlheap.obj out/bootstrap/gc.obj out/bootstrap/gc-wrapper.obj out/bootstrap/gc-invoke.obj out/bootstrap/gc-stack.obj out/bootstrap/gc-mark.obj out/bootstrap/gc-mark-range.obj out/bootstrap/gc-mark-array.obj out/bootstrap/gc-mark-class.obj out/bootstrap/gc-sweep.obj out/bootstrap/heap.obj out/bootstrap/heapfixed.obj out/bootstrap/heapvar.obj out/bootstrap/mjrtl.obj out/bootstrap/rtlheap.obj out/bootstrap/debug.obj out/bootstrap/r5rs-library.obj out/bootstrap/r5rs-native.obj out/bootstrap/r5rs-wrap.obj out/bootstrap/rtlscheme.obj out/bootstrap/scheme-main.obj + REM + schemec.exe test.scm --output test.sasm + sasm-opt.exe test.sasm --out=test.sasm-opt + sasm.exe test.sasm-opt --out=test.asm + nasm -fwin32 test.asm -o test.obj + gcc -DSCHEME_RTL=1 -Irtl rtl/mjrtl.c rtl/rtlscheme.c %RTL_OBJS% test.obj -o test.exe + .\test.exe + +Two future improvements are planned to make this more convenient: + + - A command-line tool to run the phases of the compiler automatically + - RTL lib files instead of separate obj files + diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..df74515 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,5 @@ +out/ +gmon.out +all +critical-test +*~ diff --git a/src/algo/bsearch.scm b/src/algo/bsearch.scm new file mode 100644 index 0000000..a756dd8 --- /dev/null +++ b/src/algo/bsearch.scm @@ -0,0 +1,22 @@ +;; bsearch.scm +;; +;; An implementation of binary search. + +(define (binary-search vector vector-ref vector-length less-than? value) + (define (iter low high) + (if (> low high) + #f + (let ((m (quotient (+ low high) 2))) + (cond ((less-than? (vector-ref vector m) value) + (iter (+ m 1) high)) + ((less-than? value (vector-ref vector m)) + (iter low (- m 1))) + (else m))))) + (iter 0 (- (vector-length vector) 1))) + +(define (make-binary-searcher vector-ref vector-length less-than?) + (lambda (vector value) + (binary-search vector vector-ref vector-length less-than? value))) + +(define (binary-search-vector vector less-than? value) + (binary-search vector vector-ref vector-length less-than? value)) diff --git a/src/algo/graph.scm b/src/algo/graph.scm new file mode 100644 index 0000000..16b0e92 --- /dev/null +++ b/src/algo/graph.scm @@ -0,0 +1,127 @@ +(define (graph-predecessors graph node) + (filter-map (lambda (adj) + (and (member node (cdr adj)) + (car adj))) + graph)) + +(define (graph-successors graph node) + (let ((entry (assoc node graph))) + (if (not entry) + (error "Invalid graph node -- graph-successors") + (cdr entry)))) + +(define (graph-elements graph) + (map car graph)) + +(define (graph.neighbors graph node) + (let ((l (assoc node graph))) + (if l + (cdr l) + '()))) + +(define (graph.nodes graph) + (map car graph)) + +(define (println . args) + (for-each display args) (newline)) + +(define (graph.unify graph) + (map (lambda (node) + (cons node + (remove-duplicates + equal? + (append (graph.neighbors graph node) + (filter (lambda (parent) + (member node (graph.neighbors graph + parent))) + (graph.nodes graph)))))) + (graph.nodes graph))) + +(define (graph.produce-coloring g) + (let ((graph (graph.unify g)) + (nodes (graph.nodes g))) + (let ((numbers (map (lambda (node) (cons node 0)) nodes))) + (define (num node) + (cdr (assoc node numbers))) + (define (num! node num) + (set-cdr! (assoc node numbers) num)) + (define (smallest-not-in list) + (define (iter i) + (if (member i list) + (iter (+ i 1)) + i)) + (iter 1)) + (define (dfs node) + (if (zero? (num node)) + (begin + (num! node + (smallest-not-in (map num (graph.neighbors graph node)))) + (for-each dfs (graph.neighbors graph node)) + (println node "->" (num node)) + (num node)) + (num node))) + (cond ((null? nodes) 0) + (else (dfs (car nodes)) numbers))))) + +(define (graph.remove-node graph node) + (filter (lambda (adj) (not (equal? (car adj) node))) + (map (lambda (adj) + (cons (car adj) + (filter (lambda (x) (not (equal? x node))) + (cdr adj)))) + graph))) + +(define (graph.remove-multiple-nodes graph nodes) + (if (null? nodes) + graph + (graph.remove-multiple-nodes (graph.remove-node graph (car nodes)) + (cdr nodes)))) + +(define (graph.rebuild-per-node cur-graph orig-graph node) + (let ((cur-nodes (map car cur-graph))) + (if (member node cur-nodes) + (error "node is already present in rebuilt graph -- graph.rebuild-per-node")) + (cons (cons node + (filter (lambda (x) (member x cur-nodes)) + (cdr (assoc node orig-graph)))) + (map (lambda (adj) + (cons (car adj) + (if (member node (cdr (assoc (car adj) orig-graph))) + (cons node (cdr adj)) + (cdr adj)))) + cur-graph)))) + +(define (graph.rebuild-multiple-nodes cur-graph orig-graph nodes) + (if (null? nodes) + cur-graph + (graph.rebuild-multiple-nodes (graph.rebuild-per-node cur-graph orig-graph (car nodes)) + orig-graph + (cdr nodes)))) + +(define (graph.equal? graph-a graph-b) + (and (list-set=? equal? + (map car graph-a) + (map car graph-b)) + (let iter ((adj-a graph-a)) + (if (null? adj-a) + #t + (and (list-set=? equal? + (cdr (car adj-a)) + (cdr (assoc (car (car adj-a)) graph-b))) + (iter (cdr adj-a))))))) + +(define (graph.chromatic-number graph) + (apply max (map cdr (graph.produce-coloring graph)))) + +(define g (list '(guess t1 t2 t3 t4 t5 x) + '(t1 guess x) + '(t2 guess x) + '(t3 guess x) + '(t4 guess x) + '(t5 guess x) + '(x guess t1 t2 t3 t4 t5))) + +(define t (list '(a b) + '(b c) + '(c a))) + diff --git a/src/algo/hashtable.scm b/src/algo/hashtable.scm new file mode 100644 index 0000000..3d2aa8c --- /dev/null +++ b/src/algo/hashtable.scm @@ -0,0 +1,55 @@ +;; hashtable.scm +;; A hashtable implementation that sucks. + +(need algo/quicksort) +(need algo/bsearch) + +(define (hash-lookup hash key) + (hash key)) + +(define (hash-insert! hash key value) + (hash key value)) + +(define (make-hashtable key-<) + (let ((hash (make-vector 100)) + (size 0) + (sorted? #t)) + + (define (ensure-capacity! required) + (if (> required (vector-length hash)) + (let ((new-hash (make-vector (+ required (vector-length hash))))) + (vector-copy! hash 0 size new-hash 0) + (set! hash new-hash)))) + + (define (hash-< x y) + (key-< (car x) (car y))) + + (define (ensure-sorted!) + (if (not sorted?) + (begin (quicksort-vector! hash 0 size hash-<) + (set! sorted? #t)))) + + (define (insert! key value) + (ensure-capacity! (+ size 1)) + (vector-set! hash size (cons key value)) + (set! size (+ size 1)) + (if (and sorted? + (> size 1) + (not (key-< (car (vector-ref hash (- size 2))) key))) + (set! sorted? #f))) + + (define (lookup key) + (ensure-sorted!) + (let ((index (binary-search hash + vector-ref + (lambda (x) size) + hash-< + (cons key '())))) + (and index (vector-ref hash index)))) + + (lambda (key . value) + (if (null? value) + (lookup key) + (insert! key (car value)))))) + + diff --git a/src/algo/heapsort.scm b/src/algo/heapsort.scm new file mode 100644 index 0000000..edb0658 --- /dev/null +++ b/src/algo/heapsort.scm @@ -0,0 +1,82 @@ +;; algo/heapsort.scm +;; An implementation of the textbook heapsort algorithm. + + +;; Given the index of a vector element, get the index of the left element. +(define (heapsort-left-child i) + (+ (* 2 i) 1)) + + +;; Given the index of a vector element, get the index of the right element. +(define (heapsort-right-child i) + (+ (* 2 i) 2)) + + +;; Given the index of a vector element, get the index of the parent element. +(define (heapsort-parent i) + (quotient (- i 1) 2)) + + +(define (heapsort-heapify! vec n lt?) + + ;; Following are a few convenience functions to make the code shorter. + (define (@ i) + (vector-ref vec i)) + + (define (@= i v) + (vector-set! vec i v)) + + (define (swap i j) + (let ((a (@ i))) + (@= i (@ j)) + (@= j a))) + + (define (parent i) + (heapsort-parent i)) + + (define (left-child i) + (heapsort-left-child i)) + + (define (right-child i) + (heapsort-right-child i)) + + (define (bubble-down! i) + (let ((left (left-child i)) + (right (right-child i))) + (cond ((>= i n) + vec) + ((and (< left n) (lt? (@ i) (@ left))) + (begin (swap i left) + (bubble-down! left))) + ((and (< right n) (lt? (@ i) (@ right))) + (begin (swap i right) + (bubble-down! right))) + (else + vec)))) + + ;; Perform the textbook heapsort "bubble up" operation - i.e. move the + ;; element at index i up to its proper position in the heap. + (define (bubble-up! i) + (let ((p (parent i))) + (cond ((= i (parent i)) vec) + ((lt? (@ i) (@ p)) + vec) + (else + (swap i p) + (bubble-up! p))))) + + (define (check-heap i) + (cond ((>= i n) #t) + ((and (or (>= (left-child i) n) + (lt? (@ (left-child i)) (@ i))) + (or (>= (right-child i) n) + (lt? (@ (right-child i)) (@ i)))) + (and (check-heap (left-child i)) + (check-heap (right-child i)))) + (else + #f))) + + (let loop ((idx 0)) + (if (< idx n) + (begin (heapsort-bubble-up! idx) + (loop (+ idx 1)))))) diff --git a/src/algo/lcs.scm b/src/algo/lcs.scm new file mode 100644 index 0000000..a374659 --- /dev/null +++ b/src/algo/lcs.scm @@ -0,0 +1,20 @@ +(define (lcs-recursive s1 s2) + (define (rest s) (substring s 1 (string-length s))) + (cond ((or (zero? (string-length s1)) + (zero? (string-length s2))) + 0) + ((char=? (string-ref s1 0) + (string-ref s2 0)) + (+ 1 (lcs-recursive (rest s1) (rest s2)))) + (else + (max (lcs-recursive (rest s1) s2) + (lcs-recursive s1 (rest s2)))))) + +(define (lcs-dp s1 s2) + (define table (make-vector (* (string-length s1) + (string-legnth s2)) 0)) + (define (get i j) + (vector-ref table (+ (* j (string-length s2)) i))) + (define (set! i j v) + (vector-set! table (+ (* j (string-length s2)) i) v)) + ( \ No newline at end of file diff --git a/src/algo/quicksort.scm b/src/algo/quicksort.scm new file mode 100644 index 0000000..607ae41 --- /dev/null +++ b/src/algo/quicksort.scm @@ -0,0 +1,28 @@ +(define (quicksort-vector! vector start length <=) + (define (@ i) (vector-ref vector i)) + (define (@= i v) (vector-set! vector i v)) + (define (swap i j) + (let ((tmp (@ i))) + (@= i (@ j)) + (@= j tmp))) + (define (partition beg l r end) + (swap (- l 1) beg) + (recur beg (- l 1)) + (recur r end)) + (define (recur i j) + (if (> j (+ i 1)) + (let loop ((piv (@ i)) (l (+ i 1)) (r j)) + (if (< l r) + (if (<= (@ l) piv) + (loop piv (+ l 1) r) + (begin (swap l (- r 1)) + (loop piv l (- r 1)))) + (partition i l r j))))) + (recur start length)) + +(define (quicksort! vector <=) + (quicksort-vector! vector 0 (vector-length vector) <=) + vector) + +(define (quicksort-list list <=) + (vector->list (quicksort! (list->vector list) <=))) diff --git a/src/algo/scc.scm b/src/algo/scc.scm new file mode 100644 index 0000000..d29ae91 --- /dev/null +++ b/src/algo/scc.scm @@ -0,0 +1,53 @@ +(define (memq-reverse a b) + (define (iter result rest) + (cond ((null? rest) #f) + ((eq? a (car rest)) (cons (car rest) result)) + (else (iter (cons (car rest) result) (cdr rest))))) + (iter '() b)) + +(define (find-scc nodes node-neighbors) + (let ((id 0) +; (ids '()) + (ids (multi-hash)) + (in-stack (multi-hash)) + (stack '()) + (scc-list (list-builder))) + (define (id++) (set! id (+ id 1)) id) +; (define (get-node node) (let ((r (assoc node ids))) (and r (cdr r)))) + (define (get-node node) (let ((r (multi-hash-lookup ids node))) (and r (string->number (vector-ref r 0))))) +; (define (set-node! node i) (set! ids (cons (cons node i) ids))) + (define (set-node! node i) (multi-hash-set! ids node (number->string i))) +; (define (push-node! node) (set! stack (cons node stack))) + (define (push-node! node) (set! stack (cons node stack)) (multi-hash-set! in-stack node "")) +; (define (done? node) (and (get-node node) (not (member node stack)))) + (define (done? node) (and (multi-hash-lookup ids node) (not (multi-hash-lookup in-stack node)))) + (define (pop-node node) + (let ((res (memq-reverse node stack))) + (set! stack (cdr (memq node stack))) + (for-each (lambda (n) (multi-hash-erase! in-stack n)) + res) + (multi-hash-erase! in-stack node) + res)) + (define (visit node) + (if (not (string? node)) + (begin (display "node is not string: ") (write node) (newline))) + (let ((c (get-node node))) + (if c + c + (let ((new-id (id++))) + (set-node! node new-id) + (push-node! node) + (let ((comp (apply min (cons new-id (map (lambda (n) + (if (done? n) + (+ new-id 1) + (visit n))) + (node-neighbors node)))))) + (if (= new-id comp) + (let ((scc (pop-node node))) + ;(write scc) + ;(newline) + (list-build! scc-list scc) + )) + comp))))) + (for-each visit nodes) + (list-finalize! scc-list))) diff --git a/src/ast.scm b/src/ast.scm new file mode 100644 index 0000000..384a240 --- /dev/null +++ b/src/ast.scm @@ -0,0 +1,283 @@ +(need util/list) +(need scheme/genproc) + +(define-syntax ast-node + (syntax-rules () + ((_ type (name value) ...) + (tag 'type (list (cons 'name value) ...))))) + +(define-syntax @ast + (syntax-rules () + ((_ node name) + (ast-node-attr node 'name)))) + +(define known-ast-node-types + '(program + class + method + constructor + simple-type + param + array-type + var + static-var + return-statement + user-type + compound-statement + if-statement + while-statement + print-statement + assignment-statement + array-assignment-statement + and-expression + less-than-expression + equal-to-expression + add-expression + subtract-expression + multiply-expression + int-binop-expression + int-unop-expression + not-expression + array-ref-expression + length-expression + method-call-expression + number-constant-expression + boolean-constant-expression + char-constant-expression + string-constant-expression + variable-expression + this-expression + new-array-expression + new-object-expression)) + +(define (ast-node-type node) + (get-tag node)) + +(define (ast-node-attr node attr) + (let ((entry (assoc attr (contents node)))) + (if entry + (cdr entry) + (error "AST Node " node " does not have attribute " attr)))) + +(define (ast-node? node) + (member (ast-node-type node) known-ast-node-types)) + +(define (ast-node-attr? node attr) + (if (not (ast-node? node)) + (error "Not an AST -- ast-node-attr?" node attr)) + (assoc attr (contents node))) + +(define (ast-node-attr! node attr value) + (let ((entry (assoc attr (contents node)))) + (if entry + (set-cdr! entry value) + (let ((last (terminal-pair (contents node)))) + (set-cdr! last (list (cons attr value))))))) + +(define (visit-each visitor nodes user) +; (if (not (list? nodes)) +; (begin (println "Bad nodes ") +; (write (car nodes)) +; (newline) +; (error "Unable to visit-each - not a proper list"))) + (for-each (lambda (node) (accept-visitor node visitor user)) + nodes)) + +(define (visit-each-accum visitor nodes user base accum) + (if (null? nodes) + base + (visit-each-accum visitor + (cdr nodes) + user + (let ((val (accept-visitor (car nodes) visitor user))) + (accum val base)) + accum))) + +(define (accept-visitor node visitor user) + (if (not (member (ast-node-type node) known-ast-node-types)) + (error "Accept-Visitor: unknown AST node type " node)) + (visitor (ast-node-type node) node user)) + +;; neo-ast-visitor ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; TODO - neo-ast-visitor +;; +;; - better user dispatch, i.e. user shouldn't have to do their own dispatch +;; - context; user might need to know statement corresponding to expression; +;; class corresponding to method; which sub-exp of the statement they were +;; given, etc. +;; + +(define (ast-visit-context interesting-types visit-proc . user-context) + (tag 'ast-visit-context (vector interesting-types visit-proc user-context))) + +(define (ast-visit-node ast-node context) + (let ((vec (safe-contents 'ast-visit-context context))) + (if (or (not (vector-ref vec 0)) + (member (get-tag ast-node) (vector-ref vec 0))) + (apply (vector-ref vec 1) ast-node (vector-ref vec 2))))) + +(define (ast-visit-tree ast-node context) + (ast-visit ast-node context)) + +(define (ast-visit-start ast-node context) + #t) + +(define (ast-visit-finish ast-node context) + (ast-visit-node ast-node context)) + +(define (ast-visit-trees nodes context) + (for-each (lambda (n) (ast-visit-tree n context)) + nodes)) + +(declare-genproc ast-visit) + +(define-genproc (ast-visit (p program) (ctx ast-visit-context)) + (ast-visit-start p ctx) + (ast-visit-trees (@ast p :class-list) ctx) + (ast-visit-finish p ctx)) + +(define-genproc (ast-visit (c class) (ctx ast-visit-context)) + (ast-visit-start c ctx) + (ast-visit-trees (@ast c :methods) ctx) + (ast-visit-trees (@ast c :static-methods) ctx) + (ast-visit-trees (@ast c :constructors) ctx) + (ast-visit-finish c ctx)) + +(define-genproc (ast-visit (c constructor) (ctx ast-visit-context)) + (ast-visit-start c ctx) + (ast-visit-trees (@ast c :statements) ctx) + (ast-visit-finish c ctx)) + +(define-genproc (ast-visit (m method) (ctx ast-visit-context)) + (ast-visit-start m ctx) + (ast-visit-trees (@ast m :statements) ctx) + (ast-visit-finish m ctx)) + +(define-genproc (ast-visit (stmt return-statement) (ctx ast-visit-context)) + (ast-visit-start stmt ctx) + (if (ast-node-attr? stmt ':exp) + (ast-visit-tree (@ast stmt :exp) ctx)) + (ast-visit-finish stmt ctx)) + +(define-genproc (ast-visit (stmt compound-statement) (ctx ast-visit-context)) + (ast-visit-start stmt ctx) + (ast-visit-trees (@ast stmt :statements) ctx) + (ast-visit-finish stmt ctx)) + +(define-genproc (ast-visit (stmt if-statement) (ctx ast-visit-context)) + (ast-visit-start stmt ctx) + (ast-visit-tree (@ast stmt :condition) ctx) + (ast-visit-tree (@ast stmt :consequent) ctx) + (ast-visit-tree (@ast stmt :antecedent) ctx) + (ast-visit-finish stmt ctx)) + +(define-genproc (ast-visit (stmt while-statement) (ctx ast-visit-context)) + (ast-visit-start stmt ctx) + (ast-visit-tree (@ast stmt :condition) ctx) + (ast-visit-tree (@ast stmt :body) ctx) + (ast-visit-finish stmt ctx)) + +(define-genproc (ast-visit (stmt print-statement) (ctx ast-visit-context)) + (ast-visit-start stmt ctx) + (ast-visit-tree (@ast stmt :exp) ctx) + (ast-visit-finish stmt ctx)) + +(define-genproc (ast-visit (stmt assignment-statement) (ctx ast-visit-context)) + (ast-visit-start stmt ctx) + (ast-visit-tree (@ast stmt :exp) ctx) + (ast-visit-finish stmt ctx)) + +(define-genproc (ast-visit (stmt array-assignment-statement) (ctx ast-visit-context)) + (ast-visit-start stmt ctx) + (ast-visit-tree (@ast stmt :value-exp) ctx) + (ast-visit-tree (@ast stmt :index-exp) ctx) + (ast-visit-finish stmt ctx)) + +(define-genproc (ast-visit (exp not-expression) (ctx ast-visit-context)) + (ast-visit-unop exp ctx)) + +(define-genproc (ast-visit (exp less-than-expression) (ctx ast-visit-context)) + (ast-visit-binop exp ctx)) + +(define-genproc (ast-visit (exp equal-to-expression) (ctx ast-visit-context)) + (ast-visit-binop exp ctx)) + +(define-genproc (ast-visit (exp and-expression) (ctx ast-visit-context)) + (ast-visit-binop exp ctx)) + +(define-genproc (ast-visit (exp add-expression) (ctx ast-visit-context)) + (ast-visit-binop exp ctx)) + +(define-genproc (ast-visit (exp int-binop-expression) (ctx ast-visit-context)) + (ast-visit-binop exp ctx)) + +(define-genproc (ast-visit (exp int-unop-expression) (ctx ast-visit-context)) + (ast-visit-unop exp ctx)) + +(define-genproc (ast-visit (exp subtract-expression) (ctx ast-visit-context)) + (ast-visit-binop exp ctx)) + +(define-genproc (ast-visit (exp multiply-expression) (ctx ast-visit-context)) + (ast-visit-binop exp ctx)) + +(define (ast-visit-binop exp ctx) + (ast-visit-start exp ctx) + (ast-visit-tree (@ast exp :left) ctx) + (ast-visit-tree (@ast exp :right) ctx) + (ast-visit-finish exp ctx)) + +(define (ast-visit-unop exp ctx) + (ast-visit-start exp ctx) + (ast-visit-tree (@ast exp :exp) ctx) + (ast-visit-finish exp ctx)) + +(define (ast-visit-trivial exp ctx) + (ast-visit-start exp ctx) + (ast-visit-finish exp ctx)) + +(define-genproc (ast-visit (exp array-ref-expression) (ctx ast-visit-context)) + (ast-visit-start exp ctx) + (ast-visit-tree (@ast exp :index-exp) ctx) + (ast-visit-tree (@ast exp :array-exp) ctx) + (ast-visit-finish exp ctx)) + +(define-genproc (ast-visit (exp length-expression) (ctx ast-visit-context)) + (ast-visit-unop exp ctx)) + +(define-genproc (ast-visit (exp length-expression) (ctx ast-visit-context)) + (ast-visit-trivial exp ctx)) + +(define-genproc (ast-visit (exp number-constant-expression) (ctx ast-visit-context)) + (ast-visit-trivial exp ctx)) + +(define-genproc (ast-visit (exp char-constant-expression) (ctx ast-visit-context)) + (ast-visit-trivial exp ctx)) + +(define-genproc (ast-visit (exp string-constant-expression) (ctx ast-visit-context)) + (ast-visit-trivial exp ctx)) + +(define-genproc (ast-visit (exp boolean-constant-expression) (ctx ast-visit-context)) + (ast-visit-trivial exp ctx)) + +(define-genproc (ast-visit (exp variable-expression) (ctx ast-visit-context)) + (ast-visit-trivial exp ctx)) + +(define-genproc (ast-visit (exp this-expression) (ctx ast-visit-context)) + (ast-visit-trivial exp ctx)) + +(define-genproc (ast-visit (exp new-array-expression) (ctx ast-visit-context)) + (ast-visit-start exp ctx) + (ast-visit-tree (@ast exp :length) ctx) + (ast-visit-finish exp ctx)) + +(define-genproc (ast-visit (exp new-object-expression) (ctx ast-visit-context)) + (ast-visit-start exp ctx) + (ast-visit-trees (@ast exp :arg-list) ctx) + (ast-visit-finish exp ctx)) + +(define-genproc (ast-visit (exp method-call-expression) (ctx ast-visit-context)) + (ast-visit-start exp ctx) + (ast-visit-tree (@ast exp :object) ctx) + (ast-visit-trees (@ast exp :arg-list) ctx) + (ast-visit-finish exp ctx)) diff --git a/src/bootstrap.win32.makefile b/src/bootstrap.win32.makefile new file mode 100644 index 0000000..736cca6 --- /dev/null +++ b/src/bootstrap.win32.makefile @@ -0,0 +1,1347 @@ +include sasm.dep +include sasm-opt.dep +include scheme-compiler.dep +include java-compiler.dep + +# Depends on the following environment variables which are expected to be set by running go.cmd or env.cmd: +# +# TINYSCHEMEINIT=..\bootstrap\tinyscheme-1.41\init.scm +# SCHEME=..\bootstrap\tinyscheme-1.41\scheme.exe -1 +# SASMOPT=$(SCHEME) out/sasm-opt-flat-ts.scm +# SASMC=$(SCHEME) out/sasm-flat-ts.scm +# SCHEMEC=$(SCHEME) $(SCHEMEC_FLAT_TS) +# OUTDIR=out\bootstrap + +ifndef TINYSCHEMEINIT +$(error TINYSCHEMEINIT not defined, run go.cmd or env.cmd) +endif + +ifndef SCHEME +$(error SCHEME not defined, run go.cmd or env.cmd) +endif + +ifndef SASMOPT +$(error SASMOPT not defined, run go.cmd or env.cmd) +endif + +ifndef SASMC +$(error SASMC not defined, run go.cmd or env.cmd) +endif + +ifndef SCHEMEC +$(error SCHEMEC not defined, run go.cmd or env.cmd) +endif + +ifndef OUTDIR +$(error OUTDIR not defined, run go.cmd or env.cmd) +endif + +OUT_DIR=out/.exists +BOOTSTRAP_DIR=out/bootstrap/.exists +BOOTSTRAP_TEST_DIR=out/bootstrap/test/.exists +BOOTSTRAP_TEST_JAVA_DIR=out/bootstrap/test/java/.exists +BOOTSTRAP_TEST_JAVA_GC_DIR=out/bootstrap/test/java/gc/.exists + +SCHEMEC_FLAT_TS=out/scheme-compiler-flat-ts.scm + +JAVAC_FLAT_TS=out/java-compiler-flat-ts.scm +JAVAC=$(SCHEME) $(JAVAC_FLAT_TS) + +GLUEC_FLAT_TS=out/scheme-gluec-flat-ts.scm +GLUEC=$(SCHEME) $(GLUEC_FLAT_TS) +SCHEME_CFLAGS=-DSCHEME_RTL=1 + +SCHEME_RTL=\ + out/bootstrap/r5rs-library.sasm \ + out/bootstrap/r5rs-library.sasm-opt \ + out/bootstrap/r5rs-library.asm \ + out/bootstrap/r5rs-library.obj \ + out/bootstrap/r5rs-native.sasm \ + out/bootstrap/r5rs-native.sasm-opt \ + out/bootstrap/r5rs-native.asm \ + out/bootstrap/r5rs-native.obj \ + out/bootstrap/r5rs-wrap.sasm \ + out/bootstrap/r5rs-wrap.sasm-opt \ + out/bootstrap/r5rs-wrap.asm \ + out/bootstrap/r5rs-wrap.obj \ + out/bootstrap/rtlscheme.sasm-opt \ + out/bootstrap/rtlscheme.asm \ + out/bootstrap/rtlscheme.obj + +DEPEND_OUT_DIRS=\ + $(OUT_DIR) \ + $(BOOTSTRAP_DIR) \ + $(BOOTSTRAP_TEST_DIR) \ + $(BOOTSTRAP_TEST_JAVA_DIR) + +DEPEND_EXPAND_TESTS=\ + out/bootstrap/test/apply-expanded.scm \ + out/bootstrap/test/syntax1-expanded.scm \ + out/bootstrap/test/count.sasm + +DEPEND_SCHEMEC=\ + $(SCHEMEC_FLAT_TS) + +DEPEND_JAVAC=\ + $(JAVAC_FLAT_TS) + +DEPEND_SASMOPT=\ + out/sasm-opt-flat-ts.scm + +DEPEND_SASMC=\ + out/sasm-flat-ts.scm + +DEPEND_GLUEC=\ + $(GLUEC_FLAT_TS) + +DEPEND_SASM_SIMPLE_TEST=\ + out/bootstrap/test/call.sasm-opt \ + out/bootstrap/test/call.asm \ + out/bootstrap/test/call.obj \ + out/bootstrap/test/call.exe \ + out/bootstrap/test/call.out \ + out/bootstrap/test/call.diff + +DEPEND_SCHEMEC_SIMPLE_TEST=\ + out/bootstrap/test/apply.sasm \ + out/bootstrap/test/apply.sasm-opt \ + out/bootstrap/test/apply.asm \ + out/bootstrap/test/apply.obj \ + out/bootstrap/test/apply.exe \ + out/bootstrap/test/apply.out \ + out/bootstrap/test/apply.diff \ + out/bootstrap/test/cseconds.out \ + out/bootstrap/test/disptest.out \ + out/bootstrap/test/disptest.diff \ + out/bootstrap/test/disptest2.out \ + out/bootstrap/test/disptest2.diff \ + out/bootstrap/test/argv.out \ + out/bootstrap/test/argv.diff \ + out/bootstrap/test/rename.out \ + out/bootstrap/test/rename.diff \ + out/bootstrap/test/delete.out \ + out/bootstrap/test/delete.diff \ + out/bootstrap/test/stat.out \ + out/bootstrap/test/stat.diff \ + out/bootstrap/test/getenv.out \ + out/bootstrap/test/getenv.diff \ + out/bootstrap/test/outputfile.out \ + out/bootstrap/test/outputfile.diff \ + out/bootstrap/test/inputfile.out \ + out/bootstrap/test/inputfile.diff \ + out/bootstrap/test/read.out \ + out/bootstrap/test/read.diff \ + out/bootstrap/test/read2.out \ + out/bootstrap/test/read2.diff \ + out/bootstrap/test/read3.out \ + out/bootstrap/test/read3.diff \ + out/bootstrap/test/peekchar.out \ + out/bootstrap/test/peekchar.diff \ + out/bootstrap/test/mkvec.out \ + out/bootstrap/test/mkvec.diff \ + out/bootstrap/test/eqv.out \ + out/bootstrap/test/eqv.diff \ + out/bootstrap/test/eq.out \ + out/bootstrap/test/eq.diff \ + out/bootstrap/test/vararg.out \ + out/bootstrap/test/vararg.diff \ + out/bootstrap/test/read4.out \ + out/bootstrap/test/read4.diff \ + out/bootstrap/test/read5.out \ + out/bootstrap/test/read5.diff \ + out/bootstrap/test/sym1.out \ + out/bootstrap/test/sym1.diff \ + out/bootstrap/test/opeq.out \ + out/bootstrap/test/opeq.diff \ + out/bootstrap/test/opminus.out \ + out/bootstrap/test/opminus.diff \ + out/bootstrap/test/opplus.out \ + out/bootstrap/test/opplus.diff \ + out/bootstrap/test/opgt.out \ + out/bootstrap/test/opgt.diff \ + out/bootstrap/test/oplt.out \ + out/bootstrap/test/oplt.diff \ + out/bootstrap/test/opmul.out \ + out/bootstrap/test/opmul.diff \ + out/bootstrap/test/pair.out \ + out/bootstrap/test/pair.diff \ + out/bootstrap/test/mkstring.out \ + out/bootstrap/test/mkstring.diff \ + out/bootstrap/test/str2num.out \ + out/bootstrap/test/str2num.diff \ + out/bootstrap/test/opdiv.out \ + out/bootstrap/test/opdiv.diff \ + out/bootstrap/test/char.out \ + out/bootstrap/test/char.diff \ + out/bootstrap/test/pred.out \ + out/bootstrap/test/pred.diff \ + out/bootstrap/test/write.out \ + out/bootstrap/test/write.diff \ + out/bootstrap/test/equal.out \ + out/bootstrap/test/equal.diff \ + out/bootstrap/test/r5rs1.out \ + out/bootstrap/test/r5rs1.diff \ + out/bootstrap/test/r5rs2.out \ + out/bootstrap/test/r5rs2.diff \ + out/bootstrap/test/r5rs3.out \ + out/bootstrap/test/r5rs3.diff \ + out/bootstrap/test/char-case.out \ + out/bootstrap/test/char-case.diff \ + out/bootstrap/test/string.out \ + out/bootstrap/test/string.diff \ + out/bootstrap/test/string2.out \ + out/bootstrap/test/string2.diff \ + out/bootstrap/test/string3.out \ + out/bootstrap/test/string3.diff \ + out/bootstrap/test/read6.out \ + out/bootstrap/test/read6.diff \ + out/bootstrap/test/str2num2.out \ + out/bootstrap/test/str2num2.diff \ + out/bootstrap/test/num2str.out \ + out/bootstrap/test/num2str.diff \ + out/bootstrap/test/set1.out \ + out/bootstrap/test/set1.diff \ + out/bootstrap/test/read7.out \ + out/bootstrap/test/read7.diff \ + out/bootstrap/test/read8.out \ + out/bootstrap/test/read8.diff \ + out/bootstrap/test/strref.out \ + out/bootstrap/test/strref.diff \ + out/bootstrap/test/stringset.out \ + out/bootstrap/test/stringset.diff \ + out/bootstrap/test/order-eval.out \ + out/bootstrap/test/order-eval.diff \ + out/bootstrap/test/read9.out \ + out/bootstrap/test/read9.diff \ + out/bootstrap/test/read10.out \ + out/bootstrap/test/read10.diff \ + out/bootstrap/test/read11.out \ + out/bootstrap/test/read11.diff \ + \ + out/bootstrap/test/badapply.out \ + out/bootstrap/test/badapply.diff \ + out/bootstrap/test/badvrhi.out \ + out/bootstrap/test/badvrhi.diff \ + out/bootstrap/test/badvrlo.out \ + out/bootstrap/test/badvrlo.diff \ + out/bootstrap/test/badvshi.out \ + out/bootstrap/test/badvshi.diff \ + out/bootstrap/test/badvslo.out \ + out/bootstrap/test/badvslo.diff \ + out/bootstrap/test/badsrhi.out \ + out/bootstrap/test/badsrhi.diff \ + out/bootstrap/test/badsrlo.out \ + out/bootstrap/test/badsrlo.diff \ + out/bootstrap/test/badsshi.out \ + out/bootstrap/test/badsshi.diff \ + out/bootstrap/test/badsslo.out \ + out/bootstrap/test/badsslo.diff \ + out/bootstrap/test/gc1.out + +DEPEND_RTL_OBJS=\ + out/bootstrap/c-rtlheap.obj \ + out/bootstrap/gc.obj \ + out/bootstrap/gc-wrapper.obj \ + out/bootstrap/gc-invoke.obj \ + out/bootstrap/gc-stack.obj \ + out/bootstrap/gc-mark.obj \ + out/bootstrap/gc-mark-range.obj \ + out/bootstrap/gc-mark-array.obj \ + out/bootstrap/gc-mark-class.obj \ + out/bootstrap/gc-sweep.obj \ + out/bootstrap/heap.obj \ + out/bootstrap/heapfixed.obj \ + out/bootstrap/heapvar.obj \ + out/bootstrap/mjrtl.obj \ + out/bootstrap/rtlheap.obj \ + out/bootstrap/debug.obj + +DEPEND_MJ_RTL_OBJS=\ + $(DEPEND_RTL_OBJS) + +DEPEND_MJ_RTL_C=\ + rtl/mjrtl.c + +DEPEND_MJ_RTL=\ + $(DEPEND_MJ_RTL_C) \ + $(DEPEND_RTL_OBJS) + +DEPEND_RTL_C=\ + $(DEPEND_MJ_RTL_C) \ + rtl/rtlscheme.c + +DEPEND_RTL=\ + out/bootstrap/c-rtlheap.sasm-opt \ + out/bootstrap/c-rtlheap.asm \ + out/bootstrap/gc.sasm-opt \ + out/bootstrap/gc.asm \ + out/bootstrap/heap.sasm-opt \ + out/bootstrap/heap.asm \ + out/bootstrap/heapfixed.sasm-opt \ + out/bootstrap/heapfixed.asm \ + out/bootstrap/heapvar.sasm-opt \ + out/bootstrap/heapvar.asm \ + out/bootstrap/mjrtl.sasm-opt \ + out/bootstrap/mjrtl.asm \ + out/bootstrap/rtlheap.sasm-opt \ + out/bootstrap/rtlheap.asm \ + $(DEPEND_RTL_C) \ + $(DEPEND_RTL_OBJS) + +DEPEND_SCHEME_RTL_OMIT_MAIN=\ + out/bootstrap/r5rs-library.obj \ + out/bootstrap/r5rs-native.obj \ + out/bootstrap/r5rs-wrap.obj \ + out/bootstrap/rtlscheme.obj + +DEPEND_SCHEME_RTL=\ + $(DEPEND_SCHEME_RTL_OMIT_MAIN) \ + out/bootstrap/scheme-main.obj + +DEPEND_NEEDC=\ + needc-ts.scm \ + needc.scm + +DEPEND_JAVA_TEST_OUTPUT_FILES=\ + out/bootstrap/test/java/Arrays.out \ + out/bootstrap/test/java/BinarySearch.out \ + out/bootstrap/test/java/BinaryTree.out \ + out/bootstrap/test/java/Bitwise.out \ + out/bootstrap/test/java/BubbleSort.out \ + out/bootstrap/test/java/CharString.out \ + out/bootstrap/test/java/Count.out \ + out/bootstrap/test/java/CtorTest.out \ + out/bootstrap/test/java/Factorial.out \ + out/bootstrap/test/java/LinearSearch.out \ + out/bootstrap/test/java/LinkedList.out \ + out/bootstrap/test/java/Messy.out \ + out/bootstrap/test/java/MyFactorial.out \ + out/bootstrap/test/java/NumberToString.out \ + out/bootstrap/test/java/ObjArray.out \ + out/bootstrap/test/java/OpEquals.out \ + out/bootstrap/test/java/OverrideTest.out \ + out/bootstrap/test/java/QuickSort.out \ + out/bootstrap/test/java/Rectangles.out \ + out/bootstrap/test/java/StaticMembers.out \ + out/bootstrap/test/java/StaticMethods.out \ + out/bootstrap/test/java/SubExp.out \ + out/bootstrap/test/java/TreeVisitor.out \ + out/bootstrap/test/java/TwoArgs.out + +DEPEND_JAVA_TEST_EXE_FILES=\ + $(subst %.out,%.exe,$(DEPEND_JAVA_TEST_OUTPUT_FILES)) + +DEPEND_JAVA_GC_TEST_OUTPUT_FILES=\ + out/bootstrap/test/java/gc/GCTest1.out \ + out/bootstrap/test/java/gc/GCTest2.out \ + out/bootstrap/test/java/gc/GCTest3.out \ + out/bootstrap/test/java/gc/GCTest4.out \ + out/bootstrap/test/java/gc/GCStress.out \ + out/bootstrap/test/java/gc/GCStress2.out \ + out/bootstrap/test/java/gc/GCStress3.out + +DEPEND_JAVA_GC_TEST_EXE_FILES=\ + $(subst %.out,%.exe,$(DEPEND_JAVA_GC_TEST_OUTPUT_FILES)) + +DEPEND_JAVA_GC_TEST_ASM_FILES=\ + $(subst %.out,%.asm,$(DEPEND_JAVA_GC_TEST_OUTPUT_FILES)) + +DEPEND_JAVA_GC_TEST_SASM_FILES=\ + $(subst %.out,%.sasm,$(DEPEND_JAVA_GC_TEST_OUTPUT_FILES)) + +DEPEND_JAVA_GC_TEST_SASM_OPT_FILES=\ + $(subst %.out,%.sasm-opt,$(DEPEND_JAVA_GC_TEST_OUTPUT_FILES)) + +DEPEND_JAVA_GC_TEST_FILES=\ + $(DEPEND_JAVA_GC_TEST_OUTPUT_FILES) \ + $(DEPEND_JAVA_GC_TEST_EXE_FILES) \ + $(DEPEND_JAVA_GC_TEST_ASM_FILES) \ + $(DEPEND_JAVA_GC_TEST_SASM_FILES) \ + $(DEPEND_JAVA_GC_TEST_SASM_OPT_FILES) + +DEPEND_JAVA_TEST_MARKER=\ + out/bootstrap/test/java/tests.done + +DEPEND_JAVA_GC_TEST_MARKER=\ + out/bootstrap/test/java/gc/tests.done + +DEPEND_SCHEMEC_TEST_MARKER=\ + out/bootstrap/test/schemec-tests.done + +DEPEND_ALL=\ + $(DEPEND_OUT_DIRS) \ + $(JAVAC_FLAT_TS) \ + $(SCHEMEC_FLAT_TS) \ + $(DEPEND_EXPAND_TESTS) \ + $(DEPEND_SASMOPT) \ + $(DEPEND_SASMC) \ + $(DEPEND_RTL) \ + $(SCHEME_RTL) \ + $(DEPEND_SASM_SIMPLE_TEST) \ + $(DEPEND_SCHEMEC_SIMPLE_TEST) \ + $(DEPEND_JAVA_TEST_MARKER) \ + $(DEPEND_JAVA_GC_TEST_MARKER) \ + $(DEPEND_JAVA_GC_TEST_FILES) \ + $(DEPEND_SCHEMEC_TEST_MARKER) \ + \ + out/bootstrap-sasm-ts.cmd \ + out/sasm-bootstrap.out \ + out/bootstrap/sasm.exe \ + \ + out/bootstrap-sasm-opt-ts.cmd \ + out/sasm-opt-bootstrap.out \ + out/bootstrap/sasm-opt.exe \ + \ + out/bootstrap-scheme-compiler-ts.cmd \ + out/scheme-compiler-bootstrap.out \ + out/bootstrap/schemec.exe + +all: $(DEPEND_ALL) + echo done>all + +.SECONDARY: + +out/.exists: + cmd.exe /c "if not exist out mkdir out" + cmd.exe /c "echo exists>out\.exists" + +out/bootstrap/.exists : out/.exists + cmd.exe /c "if not exist out\bootstrap mkdir out\bootstrap" + cmd.exe /c "echo exists>out\bootstrap\.exists" + +out/bootstrap/test/.exists : out/bootstrap/.exists + cmd.exe /c "if not exist out\bootstrap\test mkdir out\bootstrap\test" + cmd.exe /c "echo exists>out\bootstrap\test\.exists" + +out/bootstrap/test/java/.exists : out/bootstrap/test/.exists + cmd.exe /c "if not exist out\bootstrap\test\java mkdir out\bootstrap\test\java" + cmd.exe /c "echo exists>out\bootstrap\test\java\.exists" + +out/bootstrap/test/java/gc/.exists : out/bootstrap/test/java/.exists + cmd.exe /c "if not exist out\bootstrap\test\java\gc mkdir out\bootstrap\test\java\gc" + cmd.exe /c "echo exists>out\bootstrap\test\java\gc\.exists" + +out/scheme-compiler-flat-ts.scm : $(OUT_DIR) needc-ts.scm $(deps_of_scheme_compiler) + $(SCHEME) needc-ts.scm --output out/scheme-compiler-flat-ts.scm scheme-compiler-ts + +out/scheme-gluec-flat-ts.scm : $(OUT_DIR) needc-ts.scm scheme-gluec.scm scheme-gluec-ts.scm + $(SCHEME) needc-ts.scm --output out/scheme-gluec-flat-ts.scm scheme-gluec-ts + +out/bootstrap/test/apply-expanded.scm : tests/apply.scm $(BOOTSTRAP_TEST_DIR) $(DEPEND_SCHEMEC) + $(SCHEMEC) tests/apply.scm --output out/bootstrap/test/apply-expanded.scm --expand-only + +out/bootstrap/test/syntax1-expanded.scm : $(SCHEMEC_FLAT_TS) tests/syntax1.scm $(BOOTSTRAP_TEST_DIR) $(DEPEND_SCHEMEC) + $(SCHEMEC) tests/syntax1.scm --output out/bootstrap/test/syntax1-expanded.scm --expand-only + +# Expand, flatten minijava compiler +out/bootstrap-expand-java-compiler-ts.cmd : $(OUT_DIR) $(DEPEND_NEEDC) $(deps_of_java_compiler) + $(SCHEME) needc-ts.scm --script-mode --windows-mode --expand-only --output out\bootstrap-expand-java-compiler-ts.cmd java-compiler-ts + +out/java-compiler-expanded.out: out/bootstrap-expand-java-compiler-ts.cmd $(DEPEND_SCHEMEC) + cmd.exe /c "call env & call out\bootstrap-expand-java-compiler-ts.cmd" + cmd.exe /c "echo expanded>out\java-compiler-expanded.out" + +out/java-compiler-flat-ts.scm : out/java-compiler-expanded.out + $(SCHEME) needc-ts.scm --root out\bootstrap --flat-names --output out\java-compiler-flat-ts.scm java-compiler-ts + +# Expand, flatten sasm-opt-ts tool +out/bootstrap-expand-sasm-opt-ts.cmd : $(OUT_DIR) $(DEPEND_NEEDC) $(deps_of_sasm_opt) + $(SCHEME) needc-ts.scm --script-mode --windows-mode --expand-only --output out\bootstrap-expand-sasm-opt-ts.cmd sasm-opt-ts + +out/sasm-opt-ts-expanded.out: out/bootstrap-expand-sasm-opt-ts.cmd env.cmd $(DEPEND_SCHEMEC) + cmd.exe /c "call env.cmd & call out\bootstrap-expand-sasm-opt-ts.cmd" + cmd.exe /c "echo expanded>out\sasm-opt-ts-expanded.out" + +out/sasm-opt-flat-ts.scm : out/sasm-opt-ts-expanded.out + $(SCHEME) needc-ts.scm --root out\bootstrap --flat-names --output out\sasm-opt-flat-ts.scm sasm-opt-ts + +# Expand, flatten sasm-ts tool +out/bootstrap-expand-sasm-ts.cmd : sasm.scm $(OUT_DIR) $(DEPEND_NEEDC) $(deps_of_sasm) + $(SCHEME) needc-ts.scm --script-mode --windows-mode --expand-only --output out\bootstrap-expand-sasm-ts.cmd sasm-ts + +out/sasm-ts-expanded.out: out/bootstrap-expand-sasm-ts.cmd env.cmd $(DEPEND_SCHEMEC) + cmd.exe /c "call env.cmd & call out\bootstrap-expand-sasm-ts.cmd" + cmd.exe /c "echo expanded>out\sasm-ts-expanded.out" + +out/sasm-flat-ts.scm: out/sasm-ts-expanded.out + $(SCHEME) needc-ts.scm --root out\bootstrap --flat-names --output out\sasm-flat-ts.scm sasm-ts + +# test minijava compiler +out/bootstrap/test/java/%.sasm : tests/%.java $(BOOTSTRAP_TEST_JAVA_DIR) $(DEPEND_JAVAC) + $(JAVAC) --main=$(patsubst tests/%.java,%,$<) --out=$@ rtl/JavaRtl.java $< + +out/bootstrap/test/java/%.sasm-opt: out/bootstrap/test/java/%.sasm $(DEPEND_SASMOPT) $(BOOTSTRAP_TEST_JAVA_DIR) + $(SASMOPT) $< --out=$@ + +out/bootstrap/test/java/%.asm: out/bootstrap/test/java/%.sasm-opt $(DEPEND_SASMC) $(BOOTSTRAP_TEST_JAVA_DIR) + $(SASMC) $< --out=$@ + +out/bootstrap/test/java/%.obj: out/bootstrap/test/java/%.asm + nasm -fwin32 $< -o $@ + +out/bootstrap/test/java/%.exe: out/bootstrap/test/java/%.obj rtl/mjrtl.c $(DEPEND_MJ_RTL) + gcc -Irtl rtl/mjrtl.c $(DEPEND_MJ_RTL_OBJS) $< -o $@ + +out/bootstrap/test/java/%.out: out/bootstrap/test/java/%.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +$(DEPEND_JAVA_TEST_MARKER): $(BOOTSTRAP_TEST_JAVA_DIR) $(DEPEND_JAVA_TEST_OUTPUT_FILES) $(DEPEND_JAVA_TEST_EXE_FILES) + cmd.exe /c "echo tests.done>out\bootstrap\test\java\tests.done" + +# java GC "stress" tests +out/bootstrap/test/java/gc/%.sasm : tests/gc/%.java $(BOOTSTRAP_TEST_JAVA_GC_DIR) $(DEPEND_JAVAC) + $(JAVAC) --main=$(patsubst tests/gc/%.java,%,$<) --out=$@ rtl/JavaRtl.java $< + +out/bootstrap/test/java/gc/%.sasm-opt: out/bootstrap/test/java/gc/%.sasm $(DEPEND_SASMOPT) $(BOOTSTRAP_TEST_JAVA_GC_DIR) + $(SASMOPT) $< --out=$@ + +out/bootstrap/test/java/gc/%.asm: out/bootstrap/test/java/gc/%.sasm-opt $(DEPEND_SASMC) $(BOOTSTRAP_TEST_JAVA_GC_DIR) + $(SASMC) $< --out=$@ + +out/bootstrap/test/java/gc/%.obj: out/bootstrap/test/java/gc/%.asm + nasm -fwin32 $< -o $@ + +out/bootstrap/test/java/gc/%.exe: out/bootstrap/test/java/gc/%.obj rtl/mjrtl.c $(DEPEND_MJ_RTL) + gcc -Irtl rtl/mjrtl.c $(DEPEND_MJ_RTL_OBJS) $< -o $@ + +out/bootstrap/test/java/gc/%.out: out/bootstrap/test/java/gc/%.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +$(DEPEND_JAVA_GC_TEST_MARKER): $(BOOTSTRAP_TEST_JAVA_GC_DIR) $(DEPEND_JAVA_GC_TEST_FILES) + cmd.exe /c "echo tests.done>out\bootstrap\test\java\gc\tests.done" + +$(DEPEND_SCHEMEC_TEST_MARKER): $(BOOTSTRAP_TEST_DIR) $(DEPEND_SCHEMEC_SIMPLE_TEST) + cmd.exe /c "echo tests.done>out\bootstrap\test\schemec-tests.done" + +# Test sasmopt, sasmc - compile and run call.sasm +out/bootstrap/test/call.sasm-opt: tests/call.sasm $(DEPEND_SASMOPT) $(BOOTSTRAP_TEST_DIR) + $(SASMOPT) tests/call.sasm --out=out/bootstrap/test/call.sasm-opt + +out/bootstrap/test/call.asm: out/bootstrap/test/call.sasm-opt $(DEPEND_SASMC) $(BOOTSTRAP_TEST_DIR) + $(SASMC) out/bootstrap/test/call.sasm-opt --out=out\bootstrap\test\call.asm + +out/bootstrap/test/call.obj: out/bootstrap/test/call.asm + nasm -fwin32 out\bootstrap\test\call.asm -o out\bootstrap\test\call.obj + +out/bootstrap/test/call.exe: out/bootstrap/test/call.obj rtl/mjrtl.c + gcc -Irtl rtl/mjrtl.c $(DEPEND_RTL_OBJS) $< -o $@ + +out/bootstrap/test/call.out: out/bootstrap/test/call.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/call.diff: out/bootstrap/test/call.out tests\baseline\call.sasm-interp.actual + diff --strip-trailing-cr out/bootstrap/test/call.out tests\baseline\call.sasm-interp.actual + cmd.exe /c "echo same>out\bootstrap\test\call.diff" + +# Test scheme-compiler: apply +out/bootstrap/test/apply.sasm: tests/apply.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/apply.scm --output out\bootstrap\test\apply.sasm + +out/bootstrap/test/apply.sasm-opt: out/bootstrap/test/apply.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/apply.sasm --out=out\bootstrap\test\apply.sasm-opt + +out/bootstrap/test/apply.asm: out/bootstrap/test/apply.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/apply.sasm-opt --out=out\bootstrap\test\apply.asm + +out/bootstrap/test/apply.obj: out/bootstrap/test/apply.asm + nasm -fwin32 out\bootstrap\test\apply.asm -o out\bootstrap\test\apply.obj + +out/bootstrap/test/apply.exe: out/bootstrap/test/apply.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/apply.out: out/bootstrap/test/apply.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/apply.diff: out/bootstrap/test/apply.out tests\baseline\apply-s.actual + diff --strip-trailing-cr out/bootstrap/test/apply.out tests\baseline\apply-s.actual + cmd.exe /c "echo same>out\bootstrap\test\apply.diff" + +# Test scheme-compiler: getenv +out/bootstrap/test/getenv.sasm: tests/getenv.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/getenv.scm --output out\bootstrap\test\getenv.sasm + +out/bootstrap/test/getenv.sasm-opt: out/bootstrap/test/getenv.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/getenv.sasm --out=out\bootstrap\test\getenv.sasm-opt + +out/bootstrap/test/getenv.asm: out/bootstrap/test/getenv.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/getenv.sasm-opt --out=out\bootstrap\test\getenv.asm + +out/bootstrap/test/getenv.obj: out/bootstrap/test/getenv.asm + nasm -fwin32 out\bootstrap\test\getenv.asm -o out\bootstrap\test\getenv.obj + +out/bootstrap/test/getenv.exe: out/bootstrap/test/getenv.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/getenv.out: out/bootstrap/test/getenv.exe + cmd.exe /c "set SCHEME_TEST=SCHEME_TEST&$(subst /,\,$<) >$(subst /,\,$@.tmp)" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/getenv.diff: out/bootstrap/test/getenv.out tests\baseline\getenv-s.actual + diff --strip-trailing-cr out/bootstrap/test/getenv.out tests\baseline\getenv-s.actual + cmd.exe /c "echo same>out\bootstrap\test\getenv.diff" + +# Test scheme-compiler: cseconds +out/bootstrap/test/cseconds.sasm: tests/cseconds.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/cseconds.scm --output out\bootstrap\test\cseconds.sasm + +out/bootstrap/test/cseconds.sasm-opt: out/bootstrap/test/cseconds.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/cseconds.sasm --out=out\bootstrap\test\cseconds.sasm-opt --cheap + +out/bootstrap/test/cseconds.asm: out/bootstrap/test/cseconds.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/cseconds.sasm-opt --out=out\bootstrap\test\cseconds.asm + +out/bootstrap/test/cseconds.obj: out/bootstrap/test/cseconds.asm + nasm -fwin32 out\bootstrap\test\cseconds.asm -o out\bootstrap\test\cseconds.obj + +out/bootstrap/test/cseconds.exe: out/bootstrap/test/cseconds.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/cseconds.out: out/bootstrap/test/cseconds.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +# Test scheme-compiler: stat +out/bootstrap/test/stat.sasm: tests/stat.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/stat.scm --output out\bootstrap\test\stat.sasm + +out/bootstrap/test/stat.sasm-opt: out/bootstrap/test/stat.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/stat.sasm --out=out\bootstrap\test\stat.sasm-opt --cheap + +out/bootstrap/test/stat.asm: out/bootstrap/test/stat.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/stat.sasm-opt --out=out\bootstrap\test\stat.asm + +out/bootstrap/test/stat.obj: out/bootstrap/test/stat.asm + nasm -fwin32 out\bootstrap\test\stat.asm -o out\bootstrap\test\stat.obj + +out/bootstrap/test/stat.exe: out/bootstrap/test/stat.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/stat.out: out/bootstrap/test/stat.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/stat.diff: out/bootstrap/test/stat.out tests\baseline\stat-s.actual + diff --strip-trailing-cr out/bootstrap/test/stat.out tests\baseline\stat-s.actual + cmd.exe /c "echo same>out\bootstrap\test\stat.diff" + +# Test scheme-compiler: delete +out/bootstrap/test/delete.sasm: tests/delete.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/delete.scm --output out\bootstrap\test\delete.sasm + +out/bootstrap/test/delete.sasm-opt: out/bootstrap/test/delete.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/delete.sasm --out=out\bootstrap\test\delete.sasm-opt --cheap + +out/bootstrap/test/delete.asm: out/bootstrap/test/delete.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/delete.sasm-opt --out=out\bootstrap\test\delete.asm + +out/bootstrap/test/delete.obj: out/bootstrap/test/delete.asm + nasm -fwin32 out\bootstrap\test\delete.asm -o out\bootstrap\test\delete.obj + +out/bootstrap/test/delete.exe: out/bootstrap/test/delete.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/delete.out: out/bootstrap/test/delete.exe + cmd.exe /c "echo foo>deleteme.file" + $< >$@.tmp + cmd.exe /c "if exist deleteme.file exit /b 1" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/delete.diff: out/bootstrap/test/delete.out tests\baseline\delete-s.actual + diff --strip-trailing-cr out/bootstrap/test/delete.out tests\baseline\delete-s.actual + cmd.exe /c "echo same>out\bootstrap\test\delete.diff" + +# Test scheme-compiler: rename +out/bootstrap/test/rename.sasm: tests/rename.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/rename.scm --output out\bootstrap\test\rename.sasm + +out/bootstrap/test/rename.sasm-opt: out/bootstrap/test/rename.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/rename.sasm --out=out\bootstrap\test\rename.sasm-opt --cheap + +out/bootstrap/test/rename.asm: out/bootstrap/test/rename.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/rename.sasm-opt --out=out\bootstrap\test\rename.asm + +out/bootstrap/test/rename.obj: out/bootstrap/test/rename.asm + nasm -fwin32 out\bootstrap\test\rename.asm -o out\bootstrap\test\rename.obj + +out/bootstrap/test/rename.exe: out/bootstrap/test/rename.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/rename.out: out/bootstrap/test/rename.exe + cmd.exe /c "echo foo>from.file" + $< >$@.tmp + cmd.exe /c "if exist from.file exit /b 1" + cmd.exe /c "if not exist to.file exit /b 1" + cmd.exe /c "del to.file" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/rename.diff: out/bootstrap/test/rename.out tests\baseline\rename-s.actual + diff --strip-trailing-cr out/bootstrap/test/rename.out tests\baseline\rename-s.actual + cmd.exe /c "echo same>out\bootstrap\test\rename.diff" + +# Test scheme-compiler: argv +out/bootstrap/test/argv.sasm: tests/argv.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/argv.scm --output out\bootstrap\test\argv.sasm + +out/bootstrap/test/argv.sasm-opt: out/bootstrap/test/argv.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/argv.sasm --out=out\bootstrap\test\argv.sasm-opt --cheap + +out/bootstrap/test/argv.asm: out/bootstrap/test/argv.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/argv.sasm-opt --out=out\bootstrap\test\argv.asm + +out/bootstrap/test/argv.obj: out/bootstrap/test/argv.asm + nasm -fwin32 out\bootstrap\test\argv.asm -o out\bootstrap\test\argv.obj + +out/bootstrap/test/argv.exe: out/bootstrap/test/argv.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/argv.out: out/bootstrap/test/argv.exe + $< 1 2 3 4 five six 7 8 9 ten>$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/argv.diff: out/bootstrap/test/argv.out tests\baseline\argv-s.actual + diff --strip-trailing-cr out/bootstrap/test/argv.out tests\baseline\argv-s.actual + cmd.exe /c "echo same>out\bootstrap\test\argv.diff" + +# Test scheme-compiler: disptest +out/bootstrap/test/disptest.sasm: tests/disptest.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/disptest.scm --output out\bootstrap\test\disptest.sasm --debug + +out/bootstrap/test/disptest.sasm-opt: out/bootstrap/test/disptest.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/disptest.sasm --out=out\bootstrap\test\disptest.sasm-opt --cheap + +out/bootstrap/test/disptest.asm: out/bootstrap/test/disptest.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/disptest.sasm-opt --out=out\bootstrap\test\disptest.asm + +out/bootstrap/test/disptest.obj: out/bootstrap/test/disptest.asm + nasm -fwin32 out\bootstrap\test\disptest.asm -o out\bootstrap\test\disptest.obj + +out/bootstrap/test/disptest.exe: out/bootstrap/test/disptest.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/disptest.out: out/bootstrap/test/disptest.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/disptest.diff: out/bootstrap/test/disptest.out tests\baseline\disptest-s.actual + diff --strip-trailing-cr out/bootstrap/test/disptest.out tests\baseline\disptest-s.actual + cmd.exe /c "echo same>out\bootstrap\test\disptest.diff" + +# Test scheme-compiler: disptest2 +out/bootstrap/test/disptest2.sasm: tests/disptest2.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/disptest2.scm --output out\bootstrap\test\disptest2.sasm + +out/bootstrap/test/disptest2.sasm-opt: out/bootstrap/test/disptest2.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/disptest2.sasm --out=out\bootstrap\test\disptest2.sasm-opt --cheap + +out/bootstrap/test/disptest2.asm: out/bootstrap/test/disptest2.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/disptest2.sasm-opt --out=out\bootstrap\test\disptest2.asm + +out/bootstrap/test/disptest2.obj: out/bootstrap/test/disptest2.asm + nasm -fwin32 out\bootstrap\test\disptest2.asm -o out\bootstrap\test\disptest2.obj + +out/bootstrap/test/disptest2.exe: out/bootstrap/test/disptest2.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/disptest2.out: out/bootstrap/test/disptest2.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/disptest2.diff: out/bootstrap/test/disptest2.out tests\baseline\disptest2-s.actual + diff --strip-trailing-cr out/bootstrap/test/disptest2.out tests\baseline\disptest2-s.actual + cmd.exe /c "echo same>out\bootstrap\test\disptest2.diff" + +# Test scheme-compiler: outputfile +out/bootstrap/test/outputfile.sasm: tests/outputfile.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/outputfile.scm --output out\bootstrap\test\outputfile.sasm + +out/bootstrap/test/outputfile.sasm-opt: out/bootstrap/test/outputfile.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/outputfile.sasm --out=out\bootstrap\test\outputfile.sasm-opt --cheap + +out/bootstrap/test/outputfile.asm: out/bootstrap/test/outputfile.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/outputfile.sasm-opt --out=out\bootstrap\test\outputfile.asm + +out/bootstrap/test/outputfile.obj: out/bootstrap/test/outputfile.asm + nasm -fwin32 out\bootstrap\test\outputfile.asm -o out\bootstrap\test\outputfile.obj + +out/bootstrap/test/outputfile.exe: out/bootstrap/test/outputfile.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/outputfile.out: out/bootstrap/test/outputfile.exe + $< out/bootstrap/test/outputfile.dat>$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/outputfile.diff: out/bootstrap/test/outputfile.out tests\baseline\outputfile-s.actual + diff --strip-trailing-cr out/bootstrap/test/outputfile.out tests\baseline\outputfile-s.actual + diff --strip-trailing-cr out/bootstrap/test/outputfile.dat tests\baseline\outputfile.dat + cmd.exe /c "echo same>out\bootstrap\test\outputfile.diff" + +# Test scheme-compiler: inputfile +out/bootstrap/test/inputfile.sasm: tests/inputfile.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/inputfile.scm --output out\bootstrap\test\inputfile.sasm + +out/bootstrap/test/inputfile.sasm-opt: out/bootstrap/test/inputfile.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/inputfile.sasm --out=out\bootstrap\test\inputfile.sasm-opt --cheap + +out/bootstrap/test/inputfile.asm: out/bootstrap/test/inputfile.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/inputfile.sasm-opt --out=out\bootstrap\test\inputfile.asm + +out/bootstrap/test/inputfile.obj: out/bootstrap/test/inputfile.asm + nasm -fwin32 out\bootstrap\test\inputfile.asm -o out\bootstrap\test\inputfile.obj + +out/bootstrap/test/inputfile.exe: out/bootstrap/test/inputfile.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/inputfile.out: out/bootstrap/test/inputfile.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/inputfile.diff: out/bootstrap/test/inputfile.out tests\baseline\inputfile-s.actual + diff --strip-trailing-cr out/bootstrap/test/inputfile.out tests\baseline\inputfile-s.actual + cmd.exe /c "echo same>out\bootstrap\test\inputfile.diff" + +# Test scheme-compiler: read +out/bootstrap/test/read.sasm: tests/read.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read.scm --output out\bootstrap\test\read.sasm + +out/bootstrap/test/read-expanded.scm: tests/read.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read.scm --output out/bootstrap/test/read-expanded.scm --expand-only + +out/bootstrap/test/read.sasm-opt: out/bootstrap/test/read.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/read.sasm --out=out\bootstrap\test\read.sasm-opt --cheap + +out/bootstrap/test/read.asm: out/bootstrap/test/read.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/read.sasm-opt --out=out\bootstrap\test\read.asm + +out/bootstrap/test/read.obj: out/bootstrap/test/read.asm + nasm -fwin32 out\bootstrap\test\read.asm -o out\bootstrap\test\read.obj + +out/bootstrap/test/read.exe: out/bootstrap/test/read.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/read.out: out/bootstrap/test/read.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/read.diff: out/bootstrap/test/read.out tests\baseline\read-s.actual + diff --strip-trailing-cr out/bootstrap/test/read.out tests\baseline\read-s.actual + cmd.exe /c "echo same>out\bootstrap\test\read.diff" + +# Test scheme-compiler: read2 +out/bootstrap/test/read2.sasm: tests/read2.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read2.scm --output out\bootstrap\test\read2.sasm + +out/bootstrap/test/read2-expanded.scm: tests/read2.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read2.scm --output out/bootstrap/test/read2-expanded.scm --expand-only + +out/bootstrap/test/read2.sasm-opt: out/bootstrap/test/read2.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/read2.sasm --out=out\bootstrap\test\read2.sasm-opt --cheap + +out/bootstrap/test/read2.asm: out/bootstrap/test/read2.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/read2.sasm-opt --out=out\bootstrap\test\read2.asm + +out/bootstrap/test/read2.obj: out/bootstrap/test/read2.asm + nasm -fwin32 out\bootstrap\test\read2.asm -o out\bootstrap\test\read2.obj + +out/bootstrap/test/read2.exe: out/bootstrap/test/read2.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/read2.out: out/bootstrap/test/read2.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/read2.diff: out/bootstrap/test/read2.out tests\baseline\read2-s.actual + diff --strip-trailing-cr out/bootstrap/test/read2.out tests\baseline\read2-s.actual + cmd.exe /c "echo same>out\bootstrap\test\read2.diff" + +# Test scheme-compiler: read3 +out/bootstrap/test/read3.sasm: tests/read3.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read3.scm --output out\bootstrap\test\read3.sasm + +out/bootstrap/test/read3-expanded.scm: tests/read3.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read3.scm --output out/bootstrap/test/read3-expanded.scm --expand-only + +out/bootstrap/test/read3.sasm-opt: out/bootstrap/test/read3.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/read3.sasm --out=out\bootstrap\test\read3.sasm-opt --cheap + +out/bootstrap/test/read3.asm: out/bootstrap/test/read3.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/read3.sasm-opt --out=out\bootstrap\test\read3.asm + +out/bootstrap/test/read3.obj: out/bootstrap/test/read3.asm + nasm -fwin32 out\bootstrap\test\read3.asm -o out\bootstrap\test\read3.obj + +out/bootstrap/test/read3.exe: out/bootstrap/test/read3.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/read3.out: out/bootstrap/test/read3.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/read3.diff: out/bootstrap/test/read3.out tests\baseline\read3-s.actual + diff --strip-trailing-cr out/bootstrap/test/read3.out tests\baseline\read3-s.actual + cmd.exe /c "echo same>out\bootstrap\test\read3.diff" + + +# Test scheme-compiler: peekchar +out/bootstrap/test/peekchar.sasm: tests/peekchar.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/peekchar.scm --output out\bootstrap\test\peekchar.sasm + +out/bootstrap/test/peekchar-expanded.scm: tests/peekchar.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/peekchar.scm --output out/bootstrap/test/peekchar-expanded.scm --expand-only + +out/bootstrap/test/peekchar.sasm-opt: out/bootstrap/test/peekchar.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/peekchar.sasm --out=out\bootstrap\test\peekchar.sasm-opt --cheap + +out/bootstrap/test/peekchar.asm: out/bootstrap/test/peekchar.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/peekchar.sasm-opt --out=out\bootstrap\test\peekchar.asm + +out/bootstrap/test/peekchar.obj: out/bootstrap/test/peekchar.asm + nasm -fwin32 out\bootstrap\test\peekchar.asm -o out\bootstrap\test\peekchar.obj + +out/bootstrap/test/peekchar.exe: out/bootstrap/test/peekchar.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/peekchar.out: out/bootstrap/test/peekchar.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/peekchar.diff: out/bootstrap/test/peekchar.out tests\baseline\peekchar-s.actual + diff --strip-trailing-cr out/bootstrap/test/peekchar.out tests\baseline\peekchar-s.actual + cmd.exe /c "echo same>out\bootstrap\test\peekchar.diff" + +# Test scheme-compiler: mkvec +out/bootstrap/test/mkvec.sasm: tests/mkvec.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/mkvec.scm --output out\bootstrap\test\mkvec.sasm + +out/bootstrap/test/mkvec.sasm-opt: out/bootstrap/test/mkvec.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/mkvec.sasm --out=out\bootstrap\test\mkvec.sasm-opt --cheap + +out/bootstrap/test/mkvec.asm: out/bootstrap/test/mkvec.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/mkvec.sasm-opt --out=out\bootstrap\test\mkvec.asm + +out/bootstrap/test/mkvec.obj: out/bootstrap/test/mkvec.asm + nasm -fwin32 out\bootstrap\test\mkvec.asm -o out\bootstrap\test\mkvec.obj + +out/bootstrap/test/mkvec.exe: out/bootstrap/test/mkvec.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/mkvec.out: out/bootstrap/test/mkvec.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/mkvec.diff: out/bootstrap/test/mkvec.out tests\baseline\mkvec-s.actual + diff --strip-trailing-cr out/bootstrap/test/mkvec.out tests\baseline\mkvec-s.actual + cmd.exe /c "echo same>out\bootstrap\test\mkvec.diff" + +# Test scheme-compiler: eqv +out/bootstrap/test/eqv.sasm: tests/eqv.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/eqv.scm --output out\bootstrap\test\eqv.sasm + +out/bootstrap/test/eqv-expanded.scm: tests/eqv.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/eqv.scm --output out/bootstrap/test/eqv-expanded.scm --expand-only + +out/bootstrap/test/eqv.sasm-opt: out/bootstrap/test/eqv.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/eqv.sasm --out=out\bootstrap\test\eqv.sasm-opt --cheap + +out/bootstrap/test/eqv.asm: out/bootstrap/test/eqv.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/eqv.sasm-opt --out=out\bootstrap\test\eqv.asm + +out/bootstrap/test/eqv.obj: out/bootstrap/test/eqv.asm + nasm -fwin32 out\bootstrap\test\eqv.asm -o out\bootstrap\test\eqv.obj + +out/bootstrap/test/eqv.exe: out/bootstrap/test/eqv.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/eqv.out: out/bootstrap/test/eqv.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/eqv.diff: out/bootstrap/test/eqv.out tests\baseline\eqv-s.actual + diff --strip-trailing-cr out/bootstrap/test/eqv.out tests\baseline\eqv-s.actual + cmd.exe /c "echo same>out\bootstrap\test\eqv.diff" + +# Test scheme-compiler: eq +out/bootstrap/test/eq.sasm: tests/eq.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/eq.scm --output out\bootstrap\test\eq.sasm + +out/bootstrap/test/eq-expanded.scm: tests/eq.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/eq.scm --output out/bootstrap/test/eq-expanded.scm --expand-only + +out/bootstrap/test/eq.sasm-opt: out/bootstrap/test/eq.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/eq.sasm --out=out\bootstrap\test\eq.sasm-opt --cheap + +out/bootstrap/test/eq.asm: out/bootstrap/test/eq.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/eq.sasm-opt --out=out\bootstrap\test\eq.asm + +out/bootstrap/test/eq.obj: out/bootstrap/test/eq.asm + nasm -fwin32 out\bootstrap\test\eq.asm -o out\bootstrap\test\eq.obj + +out/bootstrap/test/eq.exe: out/bootstrap/test/eq.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/eq.out: out/bootstrap/test/eq.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/eq.diff: out/bootstrap/test/eq.out tests\baseline\eq-s.actual + diff --strip-trailing-cr out/bootstrap/test/eq.out tests\baseline\eq-s.actual + cmd.exe /c "echo same>out\bootstrap\test\eq.diff" + +# Test scheme-compiler: vararg +out/bootstrap/test/vararg.sasm: tests/vararg.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/vararg.scm --output out\bootstrap\test\vararg.sasm + +out/bootstrap/test/vararg-expanded.scm: tests/vararg.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/vararg.scm --output out/bootstrap/test/vararg-expanded.scm --expand-only + +out/bootstrap/test/vararg.sasm-opt: out/bootstrap/test/vararg.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/vararg.sasm --out=out\bootstrap\test\vararg.sasm-opt --cheap + +out/bootstrap/test/vararg.asm: out/bootstrap/test/vararg.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/vararg.sasm-opt --out=out\bootstrap\test\vararg.asm + +out/bootstrap/test/vararg.obj: out/bootstrap/test/vararg.asm + nasm -fwin32 out\bootstrap\test\vararg.asm -o out\bootstrap\test\vararg.obj + +out/bootstrap/test/vararg.exe: out/bootstrap/test/vararg.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/vararg.out: out/bootstrap/test/vararg.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/vararg.diff: out/bootstrap/test/vararg.out tests\baseline\vararg-s.actual + diff --strip-trailing-cr out/bootstrap/test/vararg.out tests\baseline\vararg-s.actual + cmd.exe /c "echo same>out\bootstrap\test\vararg.diff" + +# Test scheme-compiler: letrec +out/bootstrap/test/letrec.sasm: tests/letrec.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/letrec.scm --output out\bootstrap\test\letrec.sasm + +out/bootstrap/test/letrec-expanded.scm: tests/letrec.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/letrec.scm --output out/bootstrap/test/letrec-expanded.scm --expand-only + +out/bootstrap/test/letrec.sasm-opt: out/bootstrap/test/letrec.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/letrec.sasm --out=out\bootstrap\test\letrec.sasm-opt --cheap + +out/bootstrap/test/letrec.asm: out/bootstrap/test/letrec.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/letrec.sasm-opt --out=out\bootstrap\test\letrec.asm + +out/bootstrap/test/letrec.obj: out/bootstrap/test/letrec.asm + nasm -fwin32 out\bootstrap\test\letrec.asm -o out\bootstrap\test\letrec.obj + +out/bootstrap/test/letrec.exe: out/bootstrap/test/letrec.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/letrec.out: out/bootstrap/test/letrec.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +#out/bootstrap/test/letrec.diff: out/bootstrap/test/letrec.out tests\baseline\letrec-s.actual +# diff --strip-trailing-cr out/bootstrap/test/letrec.out tests\baseline\letrec-s.actual +# cmd.exe /c "echo same>out\bootstrap\test\letrec.diff" + +# Test scheme-compiler: read4 +out/bootstrap/test/read4.sasm: tests/read4.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read4.scm --output out\bootstrap\test\read4.sasm + +out/bootstrap/test/read4-expanded.scm: tests/read4.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read4.scm --output out/bootstrap/test/read4-expanded.scm --expand-only + +out/bootstrap/test/read4.sasm-opt: out/bootstrap/test/read4.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/read4.sasm --out=out\bootstrap\test\read4.sasm-opt --cheap + +out/bootstrap/test/read4.asm: out/bootstrap/test/read4.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/read4.sasm-opt --out=out\bootstrap\test\read4.asm + +out/bootstrap/test/read4.obj: out/bootstrap/test/read4.asm + nasm -fwin32 out\bootstrap\test\read4.asm -o out\bootstrap\test\read4.obj + +out/bootstrap/test/read4.exe: out/bootstrap/test/read4.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/read4.out: out/bootstrap/test/read4.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/read4.diff: out/bootstrap/test/read4.out tests\baseline\read4-s.actual + diff --strip-trailing-cr out/bootstrap/test/read4.out tests\baseline\read4-s.actual + cmd.exe /c "echo same>out\bootstrap\test\read4.diff" + +# Test scheme-compiler: read5 +out/bootstrap/test/read5.sasm: tests/read5.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read5.scm --output out\bootstrap\test\read5.sasm + +out/bootstrap/test/read5-expanded.scm: tests/read5.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/read5.scm --output out/bootstrap/test/read5-expanded.scm --expand-only + +out/bootstrap/test/read5.sasm-opt: out/bootstrap/test/read5.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/read5.sasm --out=out\bootstrap\test\read5.sasm-opt --cheap + +out/bootstrap/test/read5.asm: out/bootstrap/test/read5.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/read5.sasm-opt --out=out\bootstrap\test\read5.asm + +out/bootstrap/test/read5.obj: out/bootstrap/test/read5.asm + nasm -fwin32 out\bootstrap\test\read5.asm -o out\bootstrap\test\read5.obj + +out/bootstrap/test/read5.exe: out/bootstrap/test/read5.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/read5.out: out/bootstrap/test/read5.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/read5.diff: out/bootstrap/test/read5.out tests\baseline\read5-s.actual + diff --strip-trailing-cr out/bootstrap/test/read5.out tests\baseline\read5-s.actual + cmd.exe /c "echo same>out\bootstrap\test\read5.diff" + +# Test scheme-compiler: sym1 +out/bootstrap/test/sym1.sasm: tests/sym1.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/sym1.scm --output out\bootstrap\test\sym1.sasm + +out/bootstrap/test/sym1-expanded.scm: tests/sym1.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/sym1.scm --output out/bootstrap/test/sym1-expanded.scm --expand-only + +out/bootstrap/test/sym1.sasm-opt: out/bootstrap/test/sym1.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/sym1.sasm --out=out\bootstrap\test\sym1.sasm-opt --cheap + +out/bootstrap/test/sym1.asm: out/bootstrap/test/sym1.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/sym1.sasm-opt --out=out\bootstrap\test\sym1.asm + +out/bootstrap/test/sym1.obj: out/bootstrap/test/sym1.asm + nasm -fwin32 out\bootstrap\test\sym1.asm -o out\bootstrap\test\sym1.obj + +out/bootstrap/test/sym1.exe: out/bootstrap/test/sym1.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/sym1.out: out/bootstrap/test/sym1.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/sym1.diff: out/bootstrap/test/sym1.out tests\baseline\sym1-s.actual + diff --strip-trailing-cr out/bootstrap/test/sym1.out tests\baseline\sym1-s.actual + cmd.exe /c "echo same>out\bootstrap\test\sym1.diff" + +# Test scheme-compiler: badapply +out/bootstrap/test/badapply.sasm: tests/badapply.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/badapply.scm --output out\bootstrap\test\badapply.sasm + +out/bootstrap/test/badapply-expanded.scm: tests/badapply.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/badapply.scm --output out/bootstrap/test/badapply-expanded.scm --expand-only + +out/bootstrap/test/badapply.sasm-opt: out/bootstrap/test/badapply.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/badapply.sasm --out=out\bootstrap\test\badapply.sasm-opt --cheap + +out/bootstrap/test/badapply.asm: out/bootstrap/test/badapply.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/badapply.sasm-opt --out=out\bootstrap\test\badapply.asm + +out/bootstrap/test/badapply.obj: out/bootstrap/test/badapply.asm + nasm -fwin32 out\bootstrap\test\badapply.asm -o out\bootstrap\test\badapply.obj + +out/bootstrap/test/badapply.exe: out/bootstrap/test/badapply.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/badapply.out: out/bootstrap/test/badapply.exe tests/badapply.cmd + cmd.exe /c "tests\badapply.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badapply.diff: out/bootstrap/test/badapply.out tests\baseline\badapply-s.actual + diff --strip-trailing-cr out/bootstrap/test/badapply.out tests\baseline\badapply-s.actual + cmd.exe /c "echo same>out\bootstrap\test\badapply.diff" + +out/bootstrap/test/badvrhi.out: out/bootstrap/test/badvrhi.exe tests/badvrhi.cmd + cmd.exe /c "tests\badvrhi.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badvrlo.out: out/bootstrap/test/badvrlo.exe tests/badvrlo.cmd + cmd.exe /c "tests\badvrlo.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badvshi.out: out/bootstrap/test/badvshi.exe tests/badvshi.cmd + cmd.exe /c "tests\badvshi.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badvslo.out: out/bootstrap/test/badvslo.exe tests/badvslo.cmd + cmd.exe /c "tests\badvslo.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badsrhi.out: out/bootstrap/test/badsrhi.exe tests/badsrhi.cmd + cmd.exe /c "tests\badsrhi.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badsrlo.out: out/bootstrap/test/badsrlo.exe tests/badsrlo.cmd + cmd.exe /c "tests\badsrlo.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badsshi.out: out/bootstrap/test/badsshi.exe tests/badsshi.cmd + cmd.exe /c "tests\badsshi.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/badsslo.out: out/bootstrap/test/badsslo.exe tests/badsslo.cmd + cmd.exe /c "tests\badsslo.cmd>$(subst /,\,$@).tmp" + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + + +# Test scheme-compiler: gc1 +out/bootstrap/test/tests-printer.sasm: tests/printer.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/printer.scm --outdir out\bootstrap\test --conspiracy --no-entry + +out/bootstrap/test/tests-printer-helper.sasm: tests/printer-helper.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) out/bootstrap/test/tests-printer.sasm + $(SCHEMEC) tests/printer-helper.scm --outdir out\bootstrap\test --conspiracy --no-entry + +out/bootstrap/test/gc1.sasm: tests/gc1.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) out/bootstrap/test/tests-printer-helper.sasm out/bootstrap/test/tests-printer.sasm + $(SCHEMEC) tests/gc1.scm --outdir out\bootstrap\test --conspiracy + cmd.exe /c "copy out\bootstrap\test\tests-gc1.sasm out\bootstrap\test\gc1.sasm" + +out/bootstrap/test/gc1-expanded.scm: tests/gc1.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) tests/gc1.scm --output out/bootstrap/test/gc1-expanded.scm --expand-only + +out/bootstrap/test/gc1.sasm-opt: out/bootstrap/test/gc1.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/gc1.sasm --out=out\bootstrap\test\gc1.sasm-opt --cheap + +out/bootstrap/test/tests-printer.sasm-opt: out/bootstrap/test/tests-printer.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/tests-printer.sasm --out=out\bootstrap\test\tests-printer.sasm-opt --cheap + +out/bootstrap/test/tests-printer-helper.sasm-opt: out/bootstrap/test/tests-printer-helper.sasm $(DEPEND_SASMOPT) + $(SASMOPT) out/bootstrap/test/tests-printer-helper.sasm --out=out\bootstrap\test\tests-printer-helper.sasm-opt --cheap + +out/bootstrap/test/gc1.asm: out/bootstrap/test/gc1.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/gc1.sasm-opt --out=out\bootstrap\test\gc1.asm + +out/bootstrap/test/tests-printer.asm: out/bootstrap/test/tests-printer.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/tests-printer.sasm-opt --out=out\bootstrap\test\tests-printer.asm + +out/bootstrap/test/tests-printer-helper.asm: out/bootstrap/test/tests-printer-helper.sasm-opt $(DEPEND_SASMC) + $(SASMC) out/bootstrap/test/tests-printer-helper.sasm-opt --out=out\bootstrap\test\tests-printer-helper.asm + +out/bootstrap/test/gc1.obj: out/bootstrap/test/gc1.asm + nasm -fwin32 out\bootstrap\test\gc1.asm -o out\bootstrap\test\gc1.obj + +out/bootstrap/test/tests-printer.obj: out/bootstrap/test/tests-printer.asm + nasm -fwin32 out\bootstrap\test\tests-printer.asm -o out\bootstrap\test\tests-printer.obj + +out/bootstrap/test/tests-printer-helper.obj: out/bootstrap/test/tests-printer-helper.asm + nasm -fwin32 out\bootstrap\test\tests-printer-helper.asm -o out\bootstrap\test\tests-printer-helper.obj + +out/bootstrap/test/gc1.exe: out/bootstrap/test/gc1.obj out/bootstrap/test/tests-printer.obj out/bootstrap/test/tests-printer-helper.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL_OMIT_MAIN) $< out/bootstrap/test/tests-printer.obj out/bootstrap/test/tests-printer-helper.obj -o $@ + +out/bootstrap/test/gc1.out: out/bootstrap/test/gc1.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +# out/bootstrap/test/gc1.diff: out/bootstrap/test/gc1.out tests\baseline\gc1-s.actual +# diff --strip-trailing-cr out/bootstrap/test/gc1.out tests\baseline\gc1-s.actual +# cmd.exe /c "echo same>out\bootstrap\test\gc1.diff" + +out/bootstrap/test/r5rs3.out: out/bootstrap/test/r5rs3.exe + $< out/bootstrap/test/r5rs3-cwof.dat>$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +# Test scheme-compiler: general case +out/bootstrap/test/%.sasm: tests/%.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) $< --output $@ + +out/bootstrap/test/%-expanded.scm: tests/%.scm $(DEPEND_SCHEMEC) $(BOOTSTRAP_TEST_DIR) + $(SCHEMEC) $< --output $@ --expand-only + +out/bootstrap/test/%.sasm-opt: out/bootstrap/test/%.sasm $(DEPEND_SASMOPT) + $(SASMOPT) $< --out=$@ --cheap + +out/bootstrap/test/%.asm: out/bootstrap/test/%.sasm-opt $(DEPEND_SASMC) + $(SASMC) $< --out=$@ + +out/bootstrap/test/%.obj: out/bootstrap/test/%.asm + nasm -fwin32 $< -o $@ + +out/bootstrap/test/%.exe: out/bootstrap/test/%.obj $(DEPEND_RTL) $(DEPEND_SCHEME_RTL) + gcc $(SCHEME_CFLAGS) -Irtl $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL) $< -o $@ + +out/bootstrap/test/%.out: out/bootstrap/test/%.exe + $< >$@.tmp + cmd.exe /c "move $(subst /,\,$@).tmp $(subst /,\,$@)" + +out/bootstrap/test/%.diff: out/bootstrap/test/%.out tests/baseline/%-s.actual + diff --strip-trailing-cr $< $(patsubst out/bootstrap/test/%.out,tests/baseline/%-s.actual,$<) + cmd.exe /c "echo same>$(subst /,\,$@)" + + + +# Compile scheme RTL +out/bootstrap/r5rs-library.sasm: rtl/r5rs-library.scm $(DEPEND_SCHEMEC) + $(SCHEMEC) rtl/r5rs-library.scm --outdir out\bootstrap --conspiracy --no-entry + cmd.exe /c "copy out\bootstrap\rtl-r5rs-library.sasm out\bootstrap\r5rs-library.sasm" + +out/bootstrap/r5rs-library.sasm-opt : out/bootstrap/r5rs-library.sasm $(DEPEND_SASMOPT) + $(SASMOPT) $< --out=$@ --cheap + +out/bootstrap/r5rs-wrap.sasm: rtl/r5rs-wrap.scm $(DEPEND_SCHEMEC) + $(SCHEMEC) rtl/r5rs-wrap.scm --outdir out\bootstrap --conspiracy --no-entry + cmd.exe /c "copy out\bootstrap\rtl-r5rs-wrap.sasm out\bootstrap\r5rs-wrap.sasm" + +out/bootstrap/r5rs-wrap.sasm-opt : out/bootstrap/r5rs-wrap.sasm $(DEPEND_SASMOPT) + $(SASMOPT) $< --out=$@ --cheap + +out/bootstrap/r5rs-native.sasm : rtl/r5rs-native.scm $(DEPEND_GLUEC) $(BOOTSTRAP_DIR) + $(GLUEC) rtl/r5rs-native.scm -o out/bootstrap/r5rs-native.sasm + +out/bootstrap/r5rs-native.sasm-opt: out/bootstrap/r5rs-native.sasm $(DEPEND_SASMOPT) + $(SASMOPT) $< --out=$@ + +# sasm-sasm-nasmx86 override, disable-optimizations + +out/bootstrap/sasm-sasm-nasmx86.sasm-opt: out/bootstrap/sasm-sasm-nasmx86.sasm $(DEPEND_SASMOPT) + $(SASMOPT) $< --out=$@ --cheap + +# rtl rules +out/bootstrap/%.obj: out/bootstrap/%.asm + nasm -fwin32 $< -o $@ + +out/bootstrap/debug.asm: rtl/debug.asm + cmd.exe /c "copy rtl\debug.asm out\bootstrap\debug.asm" + +out/bootstrap/%.asm: out/bootstrap/%.sasm-opt $(DEPEND_SASMC) + $(SASMC) $< --out=$@ + +# bootstrap sasm tool +out/bootstrap-sasm-ts.cmd : $(OUT_DIR) $(DEPEND_NEEDC) $(deps_of_sasm) + $(SCHEME) needc-ts.scm --script-mode --windows-mode --output out\bootstrap-sasm-ts.cmd sasm + +out/sasm-bootstrap.out: out/bootstrap-sasm-ts.cmd $(DEPEND_SCHEMEC) + cmd.exe /c "call env.cmd & call out\bootstrap-sasm-ts.cmd" + cmd.exe /c "echo bootstrapped>out\sasm-bootstrap.out" + +out/bootstrap/sasm.exe: $(DEPEND_RTL) $(DEPEND_SCHEME_RTL_OMIT_MAIN) out/sasm-bootstrap.out + gcc $(SCHEME_CFLAGS) -Irtl -Lout/bootstrap $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL_OMIT_MAIN) out/bootstrap/sasm.obj -o $@ -lsasm + + +# bootstrap sasm-opt tool +out/bootstrap-sasm-opt-ts.cmd : $(OUT_DIR) $(DEPEND_NEEDC) $(deps_of_sasm_opt) + $(SCHEME) needc-ts.scm --script-mode --windows-mode --output out\bootstrap-sasm-opt-ts.cmd sasm-opt + +out/sasm-opt-bootstrap.out: out/bootstrap-sasm-opt-ts.cmd $(DEPEND_SCHEMEC) + cmd.exe /c "call env.cmd & call out\bootstrap-sasm-opt-ts.cmd" + cmd.exe /c "echo bootstrapped>out\sasm-opt-bootstrap.out" + +out/bootstrap/sasm-opt.exe: $(DEPEND_RTL) $(DEPEND_SCHEME_RTL_OMIT_MAIN) out/sasm-opt-bootstrap.out + gcc $(SCHEME_CFLAGS) -Irtl -Lout/bootstrap $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL_OMIT_MAIN) out/bootstrap/sasm-opt.obj -o $@ -lsasm-opt + + +# bootstrap schemec +out/bootstrap-scheme-compiler-ts.cmd : $(OUT_DIR) $(DEPEND_NEEDC) $(deps_of_scheme_compiler) + $(SCHEME) needc-ts.scm --script-mode --windows-mode --output out\bootstrap-scheme-compiler-ts.cmd scheme-compiler + +out/scheme-compiler-bootstrap.out: out/bootstrap-scheme-compiler-ts.cmd $(DEPEND_SCHEMEC) + cmd.exe /c "call env.cmd & call out\bootstrap-scheme-compiler-ts.cmd" + cmd.exe /c "echo bootstrapped>out\scheme-compiler-bootstrap.out" + +out/bootstrap/schemec.exe: $(DEPEND_RTL) $(DEPEND_SCHEME_RTL_OMIT_MAIN) out/scheme-compiler-bootstrap.out + gcc $(SCHEME_CFLAGS) -Irtl -Lout/bootstrap $(DEPEND_RTL_C) $(DEPEND_RTL_OBJS) $(DEPEND_SCHEME_RTL_OMIT_MAIN) out/bootstrap/scheme-compiler.obj -o $@ -lscheme-compiler + +# RTL rules which have to go under specific rules above +out/bootstrap/%.sasm-opt: rtl/%.sasm $(DEPEND_SASMOPT) + $(SASMOPT) $< --out=$@ + diff --git a/src/build.scm b/src/build.scm new file mode 100644 index 0000000..951d769 --- /dev/null +++ b/src/build.scm @@ -0,0 +1,142 @@ +(need build/rules) + +(define output-root "out/") + +(define (out . args) + (path-append output-root (apply string-append args))) + +(define (scm-command command) + (string-append "scm -b -r5 -q -lrun-scm.scm " + command)) + +(define (scm-interp-command input output) + (scm-command (string-append "scheme-interpreter.scm --conspiracy --run=" + input + " --out=" + output))) + +(define (scm-ut-command ut-name) + (scm-interp-command (string-append "tests/" ut-name ".ss") + (out ut-name "-unittest.actual"))) + +(define (scm-ut-rule ut-name) + (new-rule (list (out ut-name "-unittest.actual")) + (list (string-append "tests/" ut-name ".ss") + "scheme-interpreter.scm") + (list (scm-ut-command ut-name)))) + +(define (diff-command before after output) + (string-append "diff --strip-trailing-cr " + before + " " + after + " >" + output)) + +(define (ut-diff-command ut-name) + (diff-command (out ut-name "-unittest.actual") + (string-append "tests/baseline/" ut-name "-unittest.actual") + (out ut-name "-unittest.test"))) + + +(define (scm-ut-diff-rule ut-name) + (new-rule (list (out ut-name "-unittest.test")) + (list (string-append "tests/baseline/" ut-name "-unittest.actual") + (out ut-name "-unittest.actual")) + (list (ut-diff-command ut-name)))) + +(define (new-unit-test-rules ut-name) + (list (scm-ut-diff-rule ut-name) + (scm-ut-rule ut-name))) + +(define (compile-java-command class-name) + (scm-command (string-append "java-compiler.scm --main=" + class-name + " rtl/JavaRtl.java tests/" + class-name + ".java --out=" + (out class-name ".sasm")))) + +(define (sasm-opt-command sasm-input) + (scm-command (string-append "sasm-opt.scm " + sasm-input + " --out=" + sasm-input + "-opt"))) + +(define (java-sasm-opt-command class-name) + (sasm-opt-command (out class-name ".sasm"))) + +(define (new-compile-java-rule class-name) + (list + (new-rule (list (out class-name ".sasm")) + (list "rtl/JavaRtl.java" + (string-append "tests/" class-name ".java")) + (list (compile-java-command class-name))) + (new-rule (list (out class-name ".sasm-opt")) + (list (out class-name ".sasm")) + (list (java-sasm-opt-command class-name))) + )) + +(define (map-rules function objects) + (let loop ((objects objects) + (rules '())) + (if (null? objects) + rules + (loop (cdr objects) + (append rules (function (car objects))))))) + +(define unit-tests + (list "list" + "fastset" + "genparse" + "genproc" + "pat" + "regex" + "sasm-insn")) + +(define ut-rules + (map-rules new-unit-test-rules unit-tests)) + +(define java-class-names + (list "Arrays" + "Arrays" + "BinarySearch" + "BinaryTree" + "Bitwise" + "BubbleSort" + "CharString" + "Count" + "CtorTest" + "Factorial" + "LinearSearch" + "LinkedList" + "Messy" + "MyFactorial" + "NumberToString" + "ObjArray" + "OpEquals" + "OverrideTest" + "QuickSort" + "Rectangles" + "StaticMembers" + "StaticMethods" + "SubExp" + "TreeVisitor" + "TwoArgs" + )) + +(define java-rules + (map-rules new-compile-java-rule java-class-names)) + +(define project + (new-project + (append ut-rules + java-rules + '()))) + +(if (not (fs-exists? (read-fs "out"))) + (begin (display ";; creating output directory") + (newline) + (create-directory "out"))) +(build-project project) diff --git a/src/build/rules.scm b/src/build/rules.scm new file mode 100644 index 0000000..a1b1b4f --- /dev/null +++ b/src/build/rules.scm @@ -0,0 +1,123 @@ +(need util/string) +(need util/output-file) + +(define (path-append prefix . args) + (let loop ((result (string-append prefix "")) + (rest args)) + (if (null? rest) + result + (let* ((part (car rest)) + (next-result (if (ends-with? result "/") + (string-append result part) + (string-append result "/" part)))) + (loop next-result (cdr rest)))))) + +(define (new-exec-result success diagnostic) + (vector success diagnostic)) + +(define (exec-result-success? result) + (vector-ref result 0)) + +(define (exec-command command) + (error "exec-command currently unsupported" command)) + +;; (define (exec-command command) +;; (display command) +;; (newline) +;; (let ((start-time (current-milliseconds))) +;; (let ((int (system command))) +;; (let ((stop-time (current-milliseconds))) +;; (let ((ms-elapsed (- stop-time start-time))) +;; (display ";; elapsed time ") +;; (display ms-elapsed) +;; (display "ms") +;; (newline))) +;; (new-exec-result (zero? int) int)))) + +(define (new-rule outputs inputs commands) + (vector outputs inputs commands)) + +(define (rule-outputs rule) + (vector-ref rule 0)) + +(define (rule-inputs rule) + (vector-ref rule 1)) + +(define (rule-commands rule) + (vector-ref rule 2)) + +(define (exec-rule-commands rule) + (let loop ((commands (rule-commands rule))) + (if (null? commands) + (new-exec-result #t 0) + (let ((result (exec-command (car commands)))) + (if (exec-result-success? result) + (loop (cdr commands)) + result))))) + +(define (check-rule-inputs rule output?) + (define (inputs-exist? inputs) + (or (null? inputs) + (let ((fs (car inputs))) + (if (not (fs-exists? fs)) + (if output? + (begin + (display (string-append "don't know how to build input " + (fs-file (car inputs)))) + (newline) + #f) + #f) + (inputs-exist? (cdr inputs)))))) + + (let ((input-fs (map read-fs (rule-inputs rule)))) + (inputs-exist? input-fs))) + +(define (rule-satisfied? rule) + (check-rule-inputs rule #f)) + +(define (build-rule rule) + (define (output-newer? output inputs) + (or (null? inputs) + (let ((newer? (fs-newer? output (car inputs)))) + (if (not newer?) + (begin (display (string-append ";; input " + (fs-file (car inputs)) + " newer than output " + (fs-file output))) + (newline) + #f) + (output-newer? output (cdr inputs)))))) + + (define (all-outputs-newer? outputs inputs) + (or (null? outputs) + (and (output-newer? (car outputs) inputs) + (all-outputs-newer? (cdr outputs) inputs)))) + + (let ((input-fs (map read-fs (rule-inputs rule)))) + (if (not (check-rule-inputs rule #t)) + (error "missing inputs") + (let ((output-fs (map read-fs (rule-outputs rule)))) + (if (not (all-outputs-newer? output-fs input-fs)) + (exec-rule-commands rule)))))) + +(define (new-project rules) + (vector rules)) + +(define (project-rules project) + (vector-ref project 0)) + +(define (build-project project) + (define (build-rules rules) + (if (null? rules) + #t + (let ((rule (car rules))) + (if (rule-satisfied? rule) + (begin (build-rule rule) + (build-rules (cdr rules))) + (begin + (display "skipping rule inputs not satisfied ") + (display (rule-inputs rule)) + (newline) + (build-rules (append (cdr rules) (list rule)))))))) + (build-rules (vector-ref project 0))) + diff --git a/src/buildtags.sh b/src/buildtags.sh new file mode 100644 index 0000000..9f03796 --- /dev/null +++ b/src/buildtags.sh @@ -0,0 +1,10 @@ +if [ -x ~/.TAGStmp ]; then rm ~/.TAGStmp; fi +etags -a -f ~/.TAGStmp `find | grep '\.scm$'` +etags --language=scheme -a -f ~/.TAGStmp `find | grep '\.sasm$'` +etags -a -f ~/.TAGStmp `find | grep '\.java$'` +etags -a -f ~/.TAGStmp `find | grep '\.cs$'` +etags -a -f ~/.TAGStmp `find | grep '\.cpp$'` +etags -a -f ~/.TAGStmp `find | grep '\.c$'` +etags -a -f ~/.TAGStmp `find | grep '\.h$'` +etags -a -f ~/.TAGStmp `find | grep '\.asm$'` +mv -f ~/.TAGStmp ~/.TAGS diff --git a/src/codegen.scm b/src/codegen.scm new file mode 100644 index 0000000..3230288 --- /dev/null +++ b/src/codegen.scm @@ -0,0 +1,876 @@ +;; codegen.scm +;; SASM generator for the MiniJava frontend + +(need util/list) +(need sasm/sasm-insn) +(need pat/pat) +(need scheme/genproc) +(need ast) + +;; code-generation visitor ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(declare-genproc codegen) + +(define-genproc (codegen :codegen-program + (p program) (env global-symtab) (ctx context)) + (define main-class + (let ((main (let ((ctx (assoc 'main-class (safe-contents 'context ctx)))) + (if ctx + (lookup-class-type (cadr ctx) env) + (@ast p :main-class))))) + (if (and main + (ast-node-attr? main ':potential-main-class)) + main + (error "Could not find suitable main class")))) + (emit-code ctx + `(extern rtl-malloc)) + (emit-code ctx + `(extern mj-system-out-println)) + (emit-code ctx + `(extern cp-rtl-malloc)) + (emit-code ctx + `(extern cp-rtl-array-malloc)) + (emit-code ctx + `(extern cp-mj-system-out-println)) + (emit-code ctx + `(extern cp-rtl-array-length)) + (emit-code ctx + `(export mm-rtl-heap-begin-mark-global-vars)) + (emit-code ctx + `(export mm-rtl-heap-end-mark-global-vars)) + (emit-code ctx + `(entry ,(get-entry-point main-class))) + (emit-code ctx + `(global mm-rtl-heap-begin-mark-global-vars (const 0))) + (class-info-preamble (@ast p :class-list) env ctx) + (for-each (lambda (class) + (class-preamble class env ctx)) + (@ast p :class-list)) + (emit-code ctx + `(global mm-rtl-heap-end-mark-global-vars (const 0))) + (ast-visit p + (ast-visit-context + '(string-constant-expression) + (lambda (exp) + (codegen-declare-string-constant exp ctx)))) + (for-each (lambda (class) + (codegen class env ctx)) + (@ast p :class-list))) + +(define-genproc (codegen :codegen-class + (c class) (env global-symtab) (ctx context)) + (for-each (lambda (method) + (codegen method c env ctx)) + (append (@ast c :methods) + (@ast c :static-methods) + (@ast c :constructors)))) + +(define-genproc (codegen :codegen-method + (m method) (c class) (env global-symtab) (ctx context)) + (if (not (ast-node-attr? m ':sasm-impl-no-codegen)) + (emit-code + ctx + `(function + (name ,(class-get-method-label c m)) + (locals ,(length (@ast m :local-vars))) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const ,(length (@ast m :local-vars)))) + ,@(insn-seq:insns + (codegen-sequence-toplevel + #t + (@ast m :statements) + m + c + env + (register-target 'accum) + (return-linkage (length (@ast m :param-list)))))))))) + +(define-genproc (codegen :codegen-constructor + (ctor constructor) (c class) (env global-symtab) (ctx context)) + (emit-code + ctx + `(function + (name ,(class-get-constructor-label c ctor)) + (locals ,(length (@ast ctor :local-vars))) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const ,(length (@ast ctor :local-vars)))) + ,@(insn-seq:insns + (codegen-sequence-toplevel + #t + (ctor-append-return ctor c env + (ctor-prepend-superclass-ctor ctor c env (@ast ctor :statements))) + (ast-node method + (:return-type (@ast ctor :return-type)) + (:statements (@ast ctor :statements)) + (:static? #t) + (:virtual-ctor #t) + (:local-vars (@ast ctor :local-vars)) + (:param-list (@ast ctor :param-list))) + c + env + (register-target 'accum) + (return-linkage (length (@ast ctor :param-list))))))))) + +(define (codegen-sequence-toplevel print? stmt-seq method class env target linkage) + (cond ((null? stmt-seq) + (with-linkage (empty-insn-seq) linkage)) + ((null? (cdr stmt-seq)) + (let ((code (codegen (car stmt-seq) method class env target linkage))) + (if print? (emit-statement (car stmt-seq) code)) + code)) + (else + (let ((code (codegen (car stmt-seq) method class env target (next-linkage)))) + (if print? (emit-statement (car stmt-seq) code)) + (preserving '(this) + code + (codegen-sequence-toplevel print? (cdr stmt-seq) method class env target linkage)))))) + +(define (codegen-sequence stmt-seq method class env target linkage) + (codegen-sequence-toplevel #f stmt-seq method class env target linkage)) + +;; statements ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-genproc (codegen :codegen-return-statement + (stmt return-statement) (m method) (c class) (env global-symtab) (target ) (linkage )) + (cond ((ast-node-attr? m ':virtual-ctor) + (codegen (ast-node this-expression) m c env (register-target 'accum) (return-linkage (length (@ast m :param-list))))) + (else + (codegen (@ast stmt :exp) m c env (register-target 'accum) (return-linkage (length (@ast m :param-list))))))) + +(define-genproc (codegen :codegen-compound-statement + (stmt compound-statement) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-sequence (@ast stmt :statements) m c env target linkage)) + +(define-genproc (codegen :codegen-if-statement + (stmt if-statement) (m method) (c class) (env global-symtab) (target ) (linkage )) + (let* ((token (make-label-token)) + (f-label (make-label 'if-else token)) + (end-label (make-label 'if-done token)) + (t-linkage (if (linkage-goto? linkage) linkage (link-goto end-label)))) + (let ((p-code (codegen (@ast stmt :condition) m c env (register-target 'accum) (next-linkage))) + (t-code (codegen (@ast stmt :consequent) m c env target t-linkage)) + (f-code (codegen (@ast stmt :antecedent) m c env target linkage))) + (preserving '(this) + p-code + (append-insn-seq (insn-seq '(accum) '() + `((branch-zero (label ,f-label) + (reg accum)))) + (parallel-insn-seq + t-code + (append-insn-seq (label-insn-seq f-label) + f-code)) + (with-linkage (label-insn-seq end-label) + linkage)))))) + +(define-genproc (codegen :codegen-while-statement + (stmt while-statement) (m method) (c class) (env global-symtab) (target ) (linkage )) + (let* ((token (make-label-token)) + (end-label (make-label 'while-end token)) + (test-label (make-label 'while-test token)) + (body-label (make-label 'while-body token))) + (let ((p-code (codegen (@ast stmt :condition) m c env (register-target 'accum) (next-linkage))) + (b-code (codegen (@ast stmt :body) m c env target (next-linkage))) + (test-linkage (if (linkage-goto? linkage) linkage (link-goto end-label))) + (end-linkage (if (linkage-goto? linkage) (next-linkage) linkage))) + (preserving + '(this) + (append-insn-seq + (label-insn-seq test-label) + p-code) + (append-insn-seq + (with-linkage (insn-seq '(accum) '() + `((branch-nonzero (label ,body-label) (reg accum)))) + test-linkage) + (label-insn-seq body-label) + (preserving-loop-body '(this) b-code p-code) + (insn-seq '() '() `((goto (label ,test-label)))) + (with-linkage (label-insn-seq end-label) + end-linkage)))))) + +(define-genproc (codegen :codegen-print-statement + (stmt print-statement) (m method) (c class) (env global-symtab) (target ) (linkage )) + (preserving '(this) + (codegen (@ast stmt :exp) m c env (register-target 'accum) (next-linkage)) + (with-linkage + (insn-seq '(accum) '(accum index operand this) + `((push (reg accum)) + (perform (op call) (const cp-mj-system-out-println)))) + linkage))) + +(define-genproc (codegen :codegen-assignment-statement + (stmt assignment-statement) (m method) (c class) (env global-symtab) (target ) (linkage )) + (preserving '(this) + (codegen (@ast stmt :exp) m c env (register-target 'accum) (next-linkage)) + (codegen-store-ident (@ast stmt :ident) m c env target linkage))) + +(define (codegen-load-ident ident method class env req-target linkage) + (let ((ident-info (lookup-ident-info ident method class env)) + (cur-target #f)) + (define (get-target) + (if (not cur-target) + (set! cur-target (codegen-expression-target req-target))) + cur-target) + (if (not ident-info) + (error "No ident info load-ident " ident method class)) + (case (car ident-info) + ((local arg) + (with-expression-linkage (empty-insn-seq) + req-target + (make-target (list (car ident-info) (cdr ident-info))) + linkage)) + ((member) + (with-expression-linkage (insn-seq '(this) (exp-target-registers-modified (get-target)) + `((assign ,(exp-assign-target (get-target)) + (op load-array) + (reg this) + (const ,(+ 2 (cdr ident-info)))))) + req-target + (get-target) + linkage)) + ((static) + (with-expression-linkage (insn-seq '() (exp-target-registers-modified (get-target)) + `((assign ,(exp-assign-target (get-target)) + (op load-array) + (const ,(cdr ident-info)) + (const 0)))) + req-target + (get-target) + linkage)) + (else + (error "Bad identifier info " ident-info))) )) + +(define (codegen-store-ident ident method class env target linkage) + (let ((ident-info (lookup-ident-info ident method class env))) + (if (not ident-info) + (error "No ident info store-ident " ident method class)) + (with-linkage + (case (car ident-info) + ((local) + (insn-seq '(accum) '() + `((assign (local ,(cdr ident-info)) + (reg accum))))) + ((arg) + (insn-seq '(accum) '() + `((assign (arg ,(cdr ident-info)) + (reg accum))))) + ((member) + (insn-seq '(accum this) '() + `((perform (op store-array) + (reg this) + (const ,(+ 2 (cdr ident-info))) + (reg accum))))) + ((static) + (insn-seq '(accum) '() + `((perform (op store-array) + (const ,(cdr ident-info)) + (const 0) + (reg accum))))) + (else + (error "Bad identifier info " ident-info))) + linkage))) + +(define-genproc (codegen :codegen-array-assignment-statement + (stmt array-assignment-statement) (m method) (c class) (env global-symtab) (target ) (linkage )) + (let ((operand-code (codegen (@ast stmt :value-exp) m c env (register-target 'operand) (next-linkage))) + (index-code (codegen (@ast stmt :index-exp) m c env (register-target 'index) (next-linkage))) + (ident-code (codegen-load-ident (@ast stmt :ident) m c env (register-target 'accum) (next-linkage))) + (store-code (insn-seq '(accum index operand) '() + `((perform (op store-array) (reg accum) (reg index) (reg operand)))))) + (preserving '(this) + operand-code + (preserving '(this operand) + index-code + (preserving '(this operand index) + ident-code + (with-linkage store-code linkage)))))) + +;; boolean expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (codegen-expression-target target) + (if (null-target? target) + (make-target (make-temp 'temp (make-temp-token))) + target)) + +(define (codegen-child-expressions helper m c env target linkage . children) + (let ((child-codes (map (lambda (child) + (let* ((child-link (expression-linkage)) + (child-code (codegen child m c env (null-target) child-link)) + (child-target (expression-linkage-target child-link))) + (cons child-code + child-target))) + children)) + (current-target (codegen-expression-target target))) + (define (compute-code rest) + (if (null? rest) + (apply helper current-target (map cdr child-codes)) + (preserving '(this) + (caar rest) + (compute-code (cdr rest))))) + (with-expression-linkage + (compute-code child-codes) + target + current-target + linkage))) + +(define-genproc (codegen :codegen-not-expression + (exp not-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-child-expressions + (lambda (derived-target child-target) + (insn-seq (exp-target-registers-used child-target) + (exp-target-registers-modified derived-target) + `((assign ,(exp-assign-target derived-target) + (op bit-xor) + ,(exp-assign-target child-target) + (const 1))))) + m c env target linkage + (@ast exp :exp))) + +(define-genproc (codegen :codegen-less-than-expression + (exp less-than-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-child-expressions + (lambda (derived-target left-target right-target) + (insn-seq (append (exp-target-registers-used left-target) + (exp-target-registers-used right-target)) + (exp-target-registers-modified derived-target) + `((assign ,(exp-assign-target derived-target) + (op less-than) + ,(exp-assign-target left-target) + ,(exp-assign-target right-target))))) + m c env target linkage + (@ast exp :left) + (@ast exp :right))) + +(define-genproc (codegen :codegen-equal-to-expression + (exp equal-to-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-child-expressions + (lambda (derived-target left-target right-target) + (insn-seq (append (exp-target-registers-used left-target) + (exp-target-registers-used right-target)) + (exp-target-registers-modified derived-target) + `((assign ,(exp-assign-target derived-target) + (op equal-to) + ,(exp-assign-target left-target) + ,(exp-assign-target right-target))))) + m c env target linkage + (@ast exp :left) + (@ast exp :right))) + +(define-genproc (codegen :codegen-and-expression + (exp and-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (let* ((token (make-label-token)) + (done-label (make-label 'and-done token)) + (derived-target (codegen-expression-target target))) + (let ((lhs-code (codegen (@ast exp :left) m c env derived-target (next-linkage))) + (rhs-code (codegen (@ast exp :right) m c env derived-target (next-linkage)))) + (append-insn-seq + (preserving '(this) + lhs-code + (append-insn-seq (insn-seq (exp-target-registers-used derived-target) + '() + `((branch-zero (label ,done-label) + ,(exp-assign-target derived-target)))) + rhs-code)) + (with-expression-linkage (label-insn-seq done-label) + target + derived-target + linkage))))) + +;; binop expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (codegen-binop op exp method class env target linkage) + (codegen-child-expressions + (lambda (derived-target left right) + (insn-seq (append (exp-target-registers-used left) + (exp-target-registers-used right)) + (exp-target-registers-modified derived-target) + `((assign ,(exp-assign-target derived-target) + ,op + ,(exp-assign-target left) + ,(exp-assign-target right))))) + method class env target linkage + (@ast exp :left) + (@ast exp :right))) + +(define-genproc (codegen :codegen-add-expression + (exp add-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-binop '(op add) exp m c env target linkage)) + +(define-genproc (codegen :codegen-int-binop-expression + (exp int-binop-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-binop `(op ,(@ast exp :op)) exp m c env target linkage)) + +(define-genproc (codegen :codegen-int-unop-expresion + (exp int-unop-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-child-expressions + (lambda (derived-target child-target) + (insn-seq (exp-target-registers-used child-target) + (exp-target-registers-modified derived-target) + `((assign ,(exp-assign-target derived-target) + (op ,(@ast exp :op)) + ,(exp-assign-target child-target))))) + m c env target linkage + (@ast exp :exp))) + +(define-genproc (codegen :codegen-subtract-expression + (exp subtract-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-binop '(op sub) exp m c env target linkage)) + +(define-genproc (codegen :codegen-multiply-expression + (exp multiply-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-binop '(op mul) exp m c env target linkage)) + +;; array reference ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-genproc (codegen :codegen-array-ref-expression + (exp array-ref-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-child-expressions + (lambda (derived-target index-target array-target) + (insn-seq (append (exp-target-registers-used index-target) + (exp-target-registers-used array-target)) + (exp-target-registers-modified derived-target) + `((assign ,(exp-assign-target derived-target) + (op load-array) + ,(exp-assign-target array-target) + ,(exp-assign-target index-target))))) + m c env target linkage + (@ast exp :index-exp) + (@ast exp :array-exp))) + +;; "trivial" expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (move-accum-to-target target linkage) + (let ((actual-target (codegen-expression-target target))) + (with-expression-linkage (if (exp-target-is-specified-register? actual-target 'accum) + (empty-insn-seq) + (insn-seq (exp-target-registers-used (register-target 'accum)) + (exp-target-registers-modified actual-target) + `((assign ,(exp-assign-target actual-target) + ,(exp-assign-target (register-target 'accum)))))) + target + actual-target + linkage))) + +(define-genproc (codegen :codegen-length-expression + (exp length-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (preserving '(this) + (codegen (@ast exp :exp) m c env (register-target 'accum) (next-linkage)) + (append-insn-seq + (insn-seq '(accum) '(accum index operand this) + `((push (reg accum)) + (perform (op call) (const cp-rtl-array-length)))) + (move-accum-to-target target linkage)))) + +(define-genproc (codegen :codegen-number-constant-expression + (exp number-constant-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (with-expression-linkage (empty-insn-seq) + target + (make-target `(const ,(string->number (@ast exp :value)))) + linkage)) + +(define (codegen-parse-char-group val) + (cond ((= 1 (string-length val)) + (string-ref val 0)) + ((and (= 2 (string-length val)) + (char=? #\\ (string-ref val 0))) + (case (string-ref val 1) + ((#\r) #\return) + ((#\n) #\newline) + ((#\t) #\tab) + ((#\\) #\\) + ((#\') #\') + ((#\0) (integer->char 0)) + (else "Invalid character escape sequence" str))) + (else + (error "Invalid character literal " str)))) + +(define (codegen-parse-char-constant str) + (cond + ((char? str) + str) + ((and (starts-with? str "'") + (ends-with? str "'")) + (let ((val (substring str 1 (- (string-length str) 1)))) + (codegen-parse-char-group val))) + (else + (error "Invalid character literal " str)))) + +(define (codegen-parse-string-constant val) + (let loop ((idx 0) (result '())) + (cond ((>= idx (string-length val)) + (reverse result)) + ((and (char=? #\\ (string-ref val idx)) + (< (+ idx 1) (string-length val))) + (loop (+ idx 2) (cons (codegen-parse-char-group (substring val idx (+ idx 2))) + result))) + ((not (char=? #\\ (string-ref val idx))) + (loop (+ idx 1) (cons (codegen-parse-char-group (substring val idx (+ idx 1))) + result))) + (else + (error "Invalid character escape sequence" str idx))))) + +(define-genproc (codegen :codegen-char-constant-expression + (exp char-constant-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (with-expression-linkage (empty-insn-seq) + target + (make-target `(const ,(char->integer (codegen-parse-char-constant (@ast exp :value))))) + linkage)) + +(define-genproc (codegen :codegen-string-constant-expression + (exp string-constant-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (with-expression-linkage (empty-insn-seq) + target + (make-target `(label ,(@ast exp :strconst-label))) + linkage)) + +(define codegen-declare-string-constant + (let ((strconst-counter 0)) + (define (emit-strconst-declaration emit-code-ctx string label) + (emit-code + emit-code-ctx + `(global ,label (const ,string)))) + (define (actual-string-value exp) + (let ((str (@ast exp :value))) + (if (and (starts-with? str "\"") + (ends-with? str "\"")) + (substring str 1 (- (string-length str) 1)) + (error "Malformed string constant -- " str)))) + (lambda (exp emit-code-ctx) + (let* ((val (actual-string-value exp)) + (chars (codegen-parse-string-constant val)) + (label (begin + (set! strconst-counter (+ strconst-counter 1)) + (string->symbol (string-append "$strconst-label-" + (number->string + strconst-counter)))))) + (emit-strconst-declaration emit-code-ctx (list->string chars) label) + (ast-node-attr! exp ':strconst-label label))))) + +(define-genproc (codegen :codegen-boolean-constant-expression + (exp boolean-constant-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (with-expression-linkage (empty-insn-seq) + target + (make-target `(const ,(if (@ast exp :scheme-value) 1 0))) + linkage)) + +(define-genproc (codegen :codegen-variable-expression + (exp variable-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (codegen-load-ident (@ast exp :ident) m c env target linkage)) + +(define-genproc (codegen :codegen-this-expression + (exp this-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (with-expression-linkage (empty-insn-seq) + target + (register-target 'this) + linkage)) + +(define-genproc (codegen :codegen-new-array-expression + (exp new-array-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (preserving '(this) + (codegen (@ast exp :length) m c env (register-target 'accum) (next-linkage)) + (append-insn-seq + (insn-seq '(accum) '(accum index operand this) + `((push (reg accum)) + (perform (op call) (const cp-rtl-array-malloc)))) + (move-accum-to-target target linkage)))) + +(define-genproc (codegen :codegen-new-object-expression + (exp new-object-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (define exp-class (lookup-class-type (@ast exp :class-name) env)) + (append-insn-seq + (insn-seq '() '(accum index operand this) + `((push (const ,(class-get-word-size exp-class env))) + (perform (op call) (const cp-rtl-malloc)) + (perform (op store-array) (reg accum) (const 0) (label ,(class-get-name-label exp-class))))) + (if (not (null? (@ast exp-class :constructors))) + (append-insn-seq + (insn-seq '(accum) '(this) + `((assign (reg this) (reg accum)))) + (codegen (ast-node method-call-expression + (:object (@ast exp :class-name)) + (:explicit-method-class-name (@ast exp :class-name)) + (:explicit-method (@ast exp :target-ctor)) + (:arg-list (@ast exp :arg-list)) + (:requires-this #t) + (:constructor-call #t) + (:method-name (class-get-constructor-method-name exp-class + (@ast exp :target-ctor)))) + m c env (register-target 'accum) (next-linkage))) + (empty-insn-seq)) + (move-accum-to-target target linkage))) + +;; method call expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-genproc (codegen :codegen-method-call-expression + (exp method-call-expression) (m method) (c class) (env global-symtab) (target ) (linkage )) + (define (codegen-arg param-exp) + (append-insn-seq + (codegen param-exp m c env (register-target 'accum) (next-linkage)) + (insn-seq '(accum) '() + `((push (reg accum)))))) + (define (codegen-arg-list reverse-list) + (if (null? reverse-list) + (empty-insn-seq) + (preserving '(this) + (codegen-arg (car reverse-list)) + (codegen-arg-list (cdr reverse-list))))) + (define (get-object-class) + (cond ((ast-node-attr? exp ':explicit-method-class-name) + (lookup-class-type (@ast exp :explicit-method-class-name) env)) + ((ast-node-attr? exp ':static-method-call) + (let ((classref (@ast exp :object))) + (lookup-class-type (@ast (typecheck classref m c env) :name) env))) + (else + (let ((u (typecheck (@ast exp :object) m c env))) + (and u + (user-type? u) + (user-type->class-type u env)))))) + (define (get-method) + (cond ((ast-node-attr? exp ':explicit-method) + (@ast exp :explicit-method)) + (else + (error "Explicit method not defined for method call")))) +; NOTE - these clauses in (get-method) are out-of-date. +; codegen now assumes that typechk finds the correct method +; explicitly +; +; ((ast-node-attr? exp ':static-method-call) +; (lookup-static-method (@ast exp :method-name) +; (get-object-class) +; env)) +; (else +; (lookup-method (@ast exp :method-name) (get-object-class) env)))) + (define (get-call-op) + (cond ((tailcall? exp) + '(op tail-call)) + ((or (ast-node-attr? exp ':constructor-call) + (not (@ast (get-method) :static?))) + '(op this-call)) + (else + '(op call)))) + (define (get-tailcall-extras) + (if (tailcall? exp) + `((const ,(length (@ast exp :arg-list))) + (const ,(length (@ast m :param-list)))) + '())) + (define (get-call-insns) + (if (@ast (get-method) :static?) + (get-static-call-insns) + (get-dynamic-call-insns))) + (define (get-dynamic-call-insns) + (append-insn-seq + (codegen (@ast exp :object) m c env (register-target 'this) (next-linkage)) + (insn-seq '(this accum) '(accum index operand this) + `((assign (reg accum) (op load-array) (reg this) (const 0)) + (assign (reg accum) (op load-array) (reg accum) (const ,(+ 1 (class-get-method-offset (get-method) (get-object-class) env)))) + (perform ,(get-call-op) (reg accum) ,@(get-tailcall-extras)))))) + (define (get-static-call-insns) + (insn-seq (if (ast-node-attr? exp ':constructor-call) + '(this) + '()) + '(accum index operand this) + `((perform ,(get-call-op) (const ,(class-get-method-label (get-object-class) (get-method))) ,@(get-tailcall-extras))))) + (preserving + '(this) + (codegen-arg-list (reverse (@ast exp :arg-list))) + (preserving '(this) + (get-call-insns) + (move-accum-to-target target linkage)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (class-get-name-label class) + (string->symbol (string-append "$class_" (@ast class :class-name)))) + +(define (class-get-method-label class method) + (if (ast-node-attr? method ':static-method-alternate-identifier) + (string->symbol (@ast method :static-method-alternate-identifier)) + (let ((candidates (filter (lambda (m) (method-name=? (@ast method :name) (@ast m :name))) + (append (@ast class :methods) + (@ast class :static-methods) + (@ast class :constructors))))) + (cond ((null? candidates) + (error "Unable to derive class method label " class method)) + (else + (string->symbol (string-append "$class_" (@ast class :class-name) + "$$" (@ast method :name) + (if (= 1 (length candidates)) + "" + (number->string (index-of method eq? candidates)))))))))) + +(define (class-get-constructor-method-name class constructor) + (string-append "$ctor_" + (number->string (index-of constructor eq? (@ast class :constructors))))) + +(define (class-get-constructor-label class constructor) + (string->symbol (string-append "$class_" (@ast class :class-name) + "$$" (class-get-constructor-method-name class constructor)))) + +(define (class-get-static-var-label class static-var) + (string->symbol (string-append "$static_class_" (@ast class :class-name) + "$$" (@ast static-var :name)))) + +(define (class-find-method-in-table method-table method) + (define (find-method m table) + (cond ((null? table) #f) + ((and (method-name=? (@ast m :name) (@ast (caar table) :name)) + (methods-equivalent? m (caar table))) + table) + (else + (find-method m (cdr table))))) + (find-method method method-table)) + +(define (class-get-method-table class env) + (define (coalesce-method labeled-method table) + (let ((entry (class-find-method-in-table table (car labeled-method)))) + (if entry + (begin (set-car! entry labeled-method) + table) + (append table + (list labeled-method))))) + (define (coalesce-all labeled-methods table) + (if (null? labeled-methods) + table + (coalesce-all (cdr labeled-methods) + (coalesce-method (car labeled-methods) table)))) + (coalesce-all (map (lambda (x) (cons x (class-get-method-label class x))) + (@ast class :methods)) + (if (@ast class :parent) + (class-get-method-table (lookup-class-type (@ast class :parent) env) + env) + '()))) + +(define (class-get-method-offset method class env) + (let loop ((tab (class-get-method-table class env)) + (idx 0)) + (cond ((null? tab) + (error "Unable to find method " (@ast method :name) " in class " + (@ast class :class-name)) + #f) + ((eq? method (caar tab)) + idx) + (else + (loop (cdr tab) (+ idx 1)))))) + +(define (class-get-member-offset member class env) + (or (and (identifier-assoc member (@ast class :instance-vars)) + (+ (identifier-offset member (@ast class :instance-vars)) + (if (@ast class :parent) + (class-get-size (lookup-class-type (@ast class :parent) env) env) + 0))) + (and (@ast class :parent) + (class-get-member-offset member + (lookup-class-type (@ast class :parent) env) + env)))) + +(define (class-get-size class env) + (+ (length (@ast class :instance-vars)) + (if (@ast class :parent) + (class-get-size (lookup-class-type (@ast class :parent) env) env) + 0))) + +(define (class-get-word-size class env) + (+ 2 (class-get-size class env))) + +(define (lookup-ident-info ident method class env) + (let ((resolved (resolve-identifier ident method class env))) + (and + resolved + (case (list-ref resolved 1) + ((local) + (cons 'local + (identifier-offset ident (@ast method :local-vars)))) + ((arg) + (cons 'arg + (identifier-offset ident (@ast method :param-list)))) + ((member) + (let ((offset (class-get-member-offset ident class env))) + (and offset (cons 'member offset)))) + ((static) + (cons 'static + (class-get-static-var-label (list-ref resolved 2) + (ast-node static-var + (:name ident))))) + (else + (error "lookup-ident-info failed " ident method class env)))))) + +(define (class-preamble class env context) + (emit-code context + `(export ,(class-get-name-label class))) + (for-each (lambda (method-entry) + (emit-code context + `(export ,(cdr method-entry)))) + (class-get-method-table class env)) + (emit-code context + `(class ,(class-get-name-label class) + (const ,(class-get-size class env)) + ,@(map (lambda (x) (list 'label (cdr x))) + (class-get-method-table class env)))) + (for-each (lambda (static-var) + (emit-code context + `(global ,(class-get-static-var-label class static-var)))) + (@ast class :static-vars))) + +(define (class-info-preamble class-list env context) + (define (type-info type) + (case (ast-node-type type) + ((simple-type) (cadr (assoc (@ast type :name) + '(("int" int) ("boolean" bool) + ("void" void) ("char" char))))) + ((array-type) `(array ,(type-info (@ast type :element-type)))) + ((user-type) `(user ,(@ast type :name))) + (else (error "Invalid type node" (ast-node-type type))))) + (define (var-info var) + `(var (name ,(@ast var :name)) + (type ,(type-info (@ast var :type))))) + (define (method-info method) + `(method (name ,(@ast method :name)) + (return-type ,(type-info (@ast method :return-type))) + (param-list ,@(map var-info (@ast method :param-list))))) + (define (per-class-info class) + `(class (name ,(@ast class :class-name)) + (parent ,(@ast class :parent)) + (instance-vars ,@(map var-info (@ast class :instance-vars))) + (static-vars ,@(map var-info (@ast class :static-vars))) + (instance-methods ,@(map method-info (@ast class :methods))) + (static-methods ,@(map method-info (@ast class :static-methods))))) + (emit-code context + `(class-info + ,@(map per-class-info class-list)))) + +(define (get-entry-point main-class) + (class-get-method-label main-class (car (@ast main-class :static-methods)))) + +(define (class-find-ctor env class sig) + (find-method-by-sig sig (@ast class :constructors) env)) + +(define (ctor-prepend-superclass-ctor ctor class env statements) + (if (and (@ast class :parent) + (or (null? statements) + (not (eqv? 'super-statement (ast-node-type (car statements)))))) + (let* ((parent-class (lookup-class-type (@ast class :parent) env)) + (parent-ctor (class-find-ctor env parent-class '()))) + (if (not parent-ctor) + (if (null? (@ast parent-class :constructors)) + statements + (error "Unable to find default constructor for parent class" (@ast parent-class :constructors))) + (cons + (ast-node method-call-expression + (:object (ast-node this-expression)) + (:arg-list '()) + (:explicit-method-class-name (@ast parent-class :class-name)) + (:explicit-method parent-ctor) + (:requires-this #t) + (:constructor-call #t) + (:method-name (class-get-constructor-method-name + parent-class + parent-ctor))) + statements))) + statements)) + +(define (ctor-append-return ctor class env statements) + (let ((r (reverse statements))) + (if (and (not (null? r)) + (eqv? 'return-statement (car r))) + statements + (reverse (cons (ast-node return-statement) + r))))) diff --git a/src/compat/tinyscheme.scm b/src/compat/tinyscheme.scm new file mode 100644 index 0000000..c8f39ef --- /dev/null +++ b/src/compat/tinyscheme.scm @@ -0,0 +1,107 @@ +;; compat/tinyscheme.scm +;; +;; Definitions to make TinyScheme compatible with the project. + +;; System interface functions that were added to TinyScheme 1.41 to +;; bootstrap the system: +;; +;; (setenv ) => #unspecified +;; (getenv ) => #f | +;; +;; (delete-file ) => #unspecified +;; (create-directory ) => #unspecified +;; +;; These functions are for measuring elapsed time, and are not based on +;; any epoch, the values are meaningful only in relative terms. +;; (current-seconds) => #integer +;; (current-milliseconds) => #integer +;; +;; Used by build/rules.scm: +;; (stat ) => #f | #( +;; 0-6 - unused +;; 7 - st_size - size in bytes +;; 8 - unused +;; 9 - st_mtime - time of last modification +;; 10-N - unused +;; ) +;; +;; Used for bootstrap: +;; +;; bitwise-ior +;; bitwise-and +;; bitwise-not +;; arithmetic-shift +;; + +;; The current-error-port function is referenced by parse.scm, some of +;; the older code, and may be a mzscheme holdover. It is not defined +;; by r5rs. + +(define (current-error-port) + (current-output-port)) + +;; == R5RS Stubs == +;; +;; Stub definitions for functions specified in R5RS but missing from +;; TinyScheme. + +;; [[procedure]] (scheme-report-environment version) +;; [[procedure]] (null-environment version) + +(define (scheme-report-environment version) + (error "scheme-report-environment not supported in TinyScheme " version)) + +(define (null-environment version) + (error "null-environment not supported in TinyScheme " version)) + +;; [[procedure]] (numerator q) +;; [[procedure]] (denominator q) + +(define (numerator q) + (error "numerator not supported in TinyScheme " q)) + +(define (denominator q) + (error "denominator not supported in TinyScheme" q)) + +;; [[procedure]] (make-rectangular x1 x2) +;; [[procedure]] (make-polar x3 x) +;; [[procedure]] (real-part z) +;; [[procedure]] (imag-part z) +;; [[procedure]] (magnitude z) +;; [[procedure]] (angle z) + +(define (make-rectangular x1 x2) + (error "make-rectangular not supported in TinyScheme" x1 x2)) + +(define (make-polar x3 x) + (error "make-polar not supported in TinyScheme" x3 x)) + +(define (real-part z) + (error "real-part not supported in TinyScheme" z)) + +(define (imag-part z) + (error "imag-part not supported in TinyScheme" z)) + +(define (magnitude z) + (error "magnitude not supported in TinyScheme" z)) + +(define (angle z) + (error "angle not supported in TinyScheme" z)) + +;; == Project Functions == +;; +;; Following are dependencies on SCM or other interpreters that grew +;; in over time. +;; +;; (stat) comes from SCM/SLib, and was added in the project's fork of +;; the TinyScheme codebase. + +(define (file-exists? x) + (not (not (stat x)))) + +;; arithmetic-shift +;; bitwise-and +;; bitwise-ior + +(define *argv* (list->vector (cons "scheme-interpreter" *args*))) + diff --git a/src/csharp-compiler.scm b/src/csharp-compiler.scm new file mode 100644 index 0000000..0ee9532 --- /dev/null +++ b/src/csharp-compiler.scm @@ -0,0 +1,97 @@ +(need parse/parse) +(need regex/dfa) +(need regex/genlex) + +(need ast) +(need csharp-scanner) +(need csharp-parser) +(need types) +(need symtab) +(need typechk) +(need tailcall) +(need codegen) +(need sasm/sasm-codegen) + +(define *output-port* (current-output-port)) + +(define (emit-code context code) + (sasm-pretty-print code *output-port*) + (newline *output-port*)) + +(define (emit-statement ast-node code) + code) + +(define (parse-port port) + (let ((lex (csharp-lexically-analyze port))) + (and lex + (csharp-parse-input lex)))) + +(define (run-typecheck ast) + (let ((symtab (build-symtab ast))) + (and symtab + (let ((typecheck-result (typecheck ast symtab))) + (if (not typecheck-result) + (exit 1)) + (and typecheck-result + symtab))))) + +(define (run-codegen-analysis ast env) + (mark-tailcalls ast env) + #t) + +(define (compile port) + (let ((ast (parse-port port))) + (if (not ast) + (exit 1)) + (and ast + (let ((env (run-typecheck ast))) + (and env + (run-codegen-analysis ast env) + (codegen ast env (tag 'context '()))))))) + +(define (merge-programs program-a program-b) + (define (choose-main main-a main-b) + (cond (main-b main-b) + (main-a main-a) + (else #f))) + (define (get-main) + (choose-main (and (ast-node-attr? program-a ':main-class) (@ast program-a :main-class)) + (and (ast-node-attr? program-b ':main-class) (@ast program-b :main-class)))) + (ast-node program + (:main-class (get-main)) + (:class-list (append (@ast program-a :class-list) + (@ast program-b :class-list))))) + +(define (merge-multiple-programs list) + (accum merge-programs (car list) (cdr list))) + +(define (compile-multiple main-class programs) + (let ((asts (map (lambda (file) (call-with-input-file file parse-port)) programs))) + (and (all? (lambda (x) x) asts) + (let* ((master-program (merge-multiple-programs asts)) + (env (run-typecheck master-program))) + (and env + (run-codegen-analysis master-program env) + (codegen master-program env (tag 'context `((main-class ,main-class))))))))) + +(cond ((= 1 (vector-length *argv*)) + (compile (current-input-port))) + ((= 2 (vector-length *argv*)) + (call-with-input-file (vector-ref *argv* 1) compile)) + ((and (>= (vector-length *argv*) 3) + (starts-with? (vector-ref *argv* 1) "--main=")) + (let ((main-class-name (let ((cmd (vector-ref *argv* 1))) + (substring cmd (string-length "--main=") (string-length cmd)))) + (args + (filter (lambda (arg) + (cond + ((starts-with? arg "--out=") + (set! *output-port* + (open-output-file (string-strip-prefix arg + "--out="))) + #f) + (else #t))) + (cddr (vector->list *argv*))))) + (compile-multiple main-class-name args))) + (else + (error "Invalid command line " *argv*))) diff --git a/src/csharp-grammar.scm b/src/csharp-grammar.scm new file mode 100644 index 0000000..71fb0cd --- /dev/null +++ b/src/csharp-grammar.scm @@ -0,0 +1,736 @@ +(need parse/genparse) + +;; Note: By convention, nonterminals are prefixed with '@' and +;; terminals do not have a prefix. + +(define csharp-grammar-rules + '((@goal @program) + (:rule (lambda (x) x)) + + ;; @program + + (@program @main-class) + (:rule (lambda (x) (ast-node program (:main-class x) (:class-list (list x))))) + + (@program @main-class @class-list) + (:rule (lambda (x y) (ast-node program (:main-class x) (:class-list (cons x y))))) + + ;; @class-list + + (@class-list @class) + (:rule (lambda (x) (list x))) + + (@class-list @class-list @class) + (:rule (lambda (x y) (append x (list y)))) + + ;; @main-class + + (@main-class class ident l-curl + public static void ident l-paren string l-brak r-brak ident r-paren + l-curl @statement r-curl r-curl) + (:rule (lambda (class-1 ident-2 l-curl-3 public-4 static-5 void-6 ident-7 l-paren-8 string-9 l-brak-10 r-brak-11 ident-12 r-paren-13 l-curl-14 @statement-15 r-curl-16 r-curl-17) + (ast-node class + (:class-name (token-value ident-2)) + (:line-col (token-line-col class-1)) + (:parent #f) + (:constructors '()) + (:potential-main-class #t) + (:instance-vars '()) ; var block + (:static-vars '()) + (:methods '()) + (:static-methods + (list (ast-node method + (:name (token-value ident-7)) + (:line-col (token-line-col public-4)) + (:return-type (ast-node simple-type (:name "void"))) + (:param-list '()) + (:static? #t) + (:param-list-main + (list (ast-node param + (:type (ast-node array-type + (:line-col (token-line-col string-9)) + (:element-type (ast-node user-type + (:line-col (token-line-col string-9)) + (:name "String"))))) + (:line-col (token-line-col string-9)) + (:name (token-value ident-12))))) + (:local-vars '()) + (:statements (list @statement-15)))))))) + + ;; @class + + (@class class ident @class-body) + (:rule (lambda (class ident @class-body) + (ast-node class + (:line-col (token-line-col class)) + (:class-name (token-value ident)) + (:parent #f) + (:instance-vars (list-ref @class-body 0)) + (:static-vars (list-ref @class-body 2)) + (:methods (list-ref @class-body 1)) + (:static-methods (list-ref @class-body 3)) + (:constructors (list-ref @class-body 4)) ))) + + (@class class ident colon ident @class-body) + (:rule (lambda (class ident-name colon ident-parent @class-body) + (ast-node class + (:line-col (token-line-col class)) + (:class-name (token-value ident-name)) + (:parent (token-value ident-parent)) + (:instance-vars (list-ref @class-body 0)) + (:static-vars (list-ref @class-body 2)) + (:methods (list-ref @class-body 1)) + (:static-methods (list-ref @class-body 3)) + (:constructors (list-ref @class-body 4)) ))) + + ;; @class-body + + (@class-body l-curl @class-statement-block r-curl) + (:rule (lambda (x @class-statement-block y) + (let ((vars (filter-map (lambda (x) + (and (eqv? (car x) 'var) + (cdr x))) + @class-statement-block)) + (s-vars (filter-map (lambda (x) + (and (eqv? (car x) 'static-var) + (cdr x))) + @class-statement-block)) + (methods (filter-map (lambda (x) (and (eqv? (car x) 'method) + (not (@ast (cdr x) :static?)) + (cdr x))) + @class-statement-block)) + (s-methods (filter-map (lambda (x) (and (eqv? (car x) 'method) + (@ast (cdr x) :static?) + (cdr x))) + @class-statement-block)) + (ctors (filter-map (lambda (x) (and (eqv? 'ctor (car x)) + (cdr x))) + @class-statement-block))) + (list vars methods s-vars s-methods ctors)))) + + (@class-body l-curl r-curl) + (:rule (lambda (x y) + (list '() + '() + '() ))) + + (@class-statement-block @class-statement) + (:rule (lambda (x) (list x))) + + (@class-statement-block @class-statement-block @class-statement) + (:rule (lambda (x y) (append x (list y)))) + + (@class-statement @var) + (:rule (lambda (@var) (cons 'var @var))) + + (@class-statement @static-var) + (:rule (lambda (@static-var) (cons 'static-var @static-var))) + + (@class-statement @method) + (:rule (lambda (@method) (cons 'method @method))) + + (@class-statement @constructor) + (:rule (lambda (@constructor) (cons 'ctor @constructor))) + + ;; @var-block + + (@var-block @var) + (:rule (lambda (v) + (list v))) + + (@var-block @var-block @var) + (:rule (lambda (@var-block @var) + (append @var-block (list @var)))) + + ;; @var + + (@var @type ident s-colon) + (:rule (lambda (@type ident s-colon) + (ast-node var + (:line-col (@ast @type :line-col)) + (:name (token-value ident)) + (:type @type)))) + + ;; @static-var + + (@static-var static @type ident s-colon) + (:rule (lambda (x @type ident s-colon) + (ast-node static-var + (:line-col (token-line-col x)) + (:name (token-value ident)) + (:type @type)))) + + ;; @constructor + + (@constructor public ident l-paren r-paren @method-body) + (:rule (lambda (x ident y z @method-body) + (ast-node constructor + (:line-col (list-ref x 2)) + (:param-list '()) + (:static? #t) + (:return-type (ast-node user-type (:name (token-value ident)))) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1)) ) )) + + (@constructor public ident l-paren @param-list r-paren @method-body) + (:rule (lambda (--x ident --y @param-list --z @method-body) + (ast-node constructor + (:line-col (list-ref --x 2)) + (:param-list @param-list) + (:static? #t) + (:return-type (ast-node user-type (:name (token-value ident)))) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1)) ) )) + + ;; @method + + (@method @method-start r-paren @method-body) + (:rule (lambda (@method-start r-paren @method-body) + (ast-node method + (:line-col (list-ref @method-start 2)) + (:name (list-ref @method-start 1)) + (:param-list '()) + (:return-type (list-ref @method-start 0)) + (:static? (list-ref @method-start 3)) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1))))) + + (@method @method-start @param-list r-paren @method-body) + (:rule (lambda (@method-start @param-list r-paren @method-body) + (ast-node method + (:line-col (list-ref @method-start 2)) + (:name (list-ref @method-start 1)) + (:param-list @param-list) + (:return-type (list-ref @method-start 0)) + (:static? (list-ref @method-start 3)) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1))))) + + (@method --sasm-impl public static @type @method-ident l-paren @param-list r-paren s-colon) + (:rule (lambda (--sasm-impl --public --static @type @method-ident --l-paren @param-list --r-paren --s-colon) + (ast-node method + (:sasm-impl-no-codegen #t) + (:line-col (token-line-col --sasm-impl)) + (:name (token-value @method-ident)) + (:param-list @param-list) + (:return-type @type) + (:static? #t) + (:local-vars '()) + (:statements '())))) + + (@method --sasm-impl public static @type @method-ident l-paren @param-list r-paren = ident s-colon) + (:rule (lambda (--sasm-impl --public --static @type method-name@method-ident --l-paren @param-list --r-paren --= sasm-ident@method-ident --s-colon) + (ast-node method + (:sasm-impl-no-codegen #t) + (:static-method-alternate-identifier (token-value sasm-ident@method-ident)) + (:line-col (token-line-col --sasm-impl)) + (:name (token-value method-name@method-ident)) + (:param-list @param-list) + (:return-type @type) + (:static? #t) + (:local-vars '()) + (:statements '())))) + + ;; @method-start + + (@method-start virtual public @type @method-ident l-paren) + (:rule (lambda (x y @type ident z) + (list @type (token-value ident) (token-line-col x) #f))) + + (@method-start override public @type @method-ident l-paren) + (:rule (lambda (x y @type ident z) + (list @type (token-value ident) (token-line-col x) #f))) + + (@method-start public static @type @method-ident l-paren) + (:rule (lambda (x y @type ident z) + (list @type (token-value ident) (token-line-col x) #t))) + + (@method-ident ident) + (:rule (lambda (x) x)) + + (@method-ident length) + (:rule (lambda (x) x)) + + ;; @param-list + + (@param-list @param) + (:rule (lambda (x) (list x))) + + (@param-list @param-list comma @param) + (:rule (lambda (a comma b) (append a (list b)))) + + ;; @param + + (@param @type ident) + (:rule (lambda (@type ident) + (ast-node param + (:line-col (@ast @type :line-col)) + (:type @type) + (:name (token-value ident))))) + + ;; @method-body + + (@method-body l-curl @var-block @statement-block r-curl) + (:rule (lambda (l-curl @var-block @statement-block r-curl) + (list @var-block + @statement-block))) + + (@method-body l-curl @statement-block r-curl) + (:rule (lambda (l-curl @statement-block r-curl) + (list '() + @statement-block))) + + (@method-body l-curl r-curl) + (:rule (lambda (l-curl r-curl) + (list '() '()))) + + ;; @statement-block + + (@statement-block @statement) + (:rule (lambda (x) (list x))) + + (@statement-block @statement-block @statement) + (:rule (lambda (x y) (append x (list y)))) + + ;; @type + + (@type int l-brak r-brak) + (:rule (lambda (x y z) + (ast-node array-type + (:line-col (token-line-col x)) + (:element-type (ast-node simple-type + (:name "int")))))) + + (@type char l-brak r-brak) + (:rule (lambda (x y z) + (ast-node array-type + (:line-col (token-line-col x)) + (:element-type (ast-node simple-type + (:name "char")))))) + + (@type string l-brak r-brak) + (:rule (lambda (x y z) + (ast-node array-type + (:line-col (token-line-col x)) + (:element-type (ast-node user-type + (:name "String")))))) + + (@type ident l-brak r-brak) + (:rule (lambda (ident y z) + (ast-node array-type + (:line-col (token-line-col ident)) + (:element-type (ast-node user-type + (:name (token-value ident))))))) + + (@type boolean) + (:rule (lambda (x) + (ast-node simple-type + (:line-col (token-line-col x)) + (:name "boolean")))) + + (@type int) + (:rule (lambda (x) + (ast-node simple-type + (:line-col (token-line-col x)) + (:name "int")))) + + (@type string) + (:rule (lambda (x) + (ast-node user-type + (:line-col (token-line-col x)) + (:name "String")))) + + (@type char) + (:rule (lambda (x) + (ast-node simple-type + (:line-col (token-line-col x)) + (:name "char")))) + + (@type ident) + (:rule (lambda (ident) + (ast-node user-type + (:line-col (token-line-col ident)) + (:name (token-value ident))))) + + ;; @statement + + (@statement l-curl r-curl) + (:rule (lambda (x y) + (ast-node compound-statement + (:line-col (token-line-col x)) + (:statements '())))) + + (@statement l-curl @statement-block r-curl) + (:rule (lambda (x @statement-block z) + (ast-node compound-statement + (:line-col (token-line-col x)) + (:statements @statement-block)))) + + (@statement if l-paren @exp r-paren @statement else @statement) + (:rule (lambda (if-tok l-paren @exp r-paren @statement-consequent else @statement-antecedent) + (ast-node if-statement + (:line-col (token-line-col if-tok)) + (:condition @exp) + (:consequent @statement-consequent) + (:antecedent @statement-antecedent)))) + + (@statement while l-paren @exp r-paren @statement) + (:rule (lambda (while l-paren @exp r-paren @statement) + (ast-node while-statement + (:line-col (token-line-col while)) + (:condition @exp) + (:body @statement)))) + + (@statement system-console-writeline l-paren @exp r-paren s-colon) + (:rule (lambda (x y @exp z w) + (ast-node print-statement + (:line-col (token-line-col x)) + (:exp @exp)))) + + (@statement ident = @exp s-colon) + (:rule (lambda (ident x @exp y) + (ast-node assignment-statement + (:line-col (token-line-col ident)) + (:ident (token-value ident)) + (:exp @exp)))) + + (@statement ident l-brak @exp r-brak = @exp s-colon) + (:rule (lambda (ident x @index-exp y z @value-exp w) + (ast-node array-assignment-statement + (:line-col (token-line-col ident)) + (:ident (token-value ident)) + (:index-exp @index-exp) + (:value-exp @value-exp)))) + + (@statement return @exp s-colon) + (:rule (lambda (r @exp s) + (ast-node return-statement + (:line-col (token-line-col r)) + (:exp @exp)))) + + (@statement return s-colon) + (:rule (lambda (r s) + (ast-node return-statement + (:line-col (token-line-col r))))) + + ;; @exp + + (@exp @exp-logical) + (:rule (lambda (x) x)) + + ;; @exp-logical + + (@exp-logical @exp-comparison) + (:rule (lambda (x) x)) + + (@exp-logical @exp-logical && @exp-comparison) + (:rule (lambda (@exp-logical foo @exp-comparison) + (ast-node and-expression + (:line-col (token-line-col foo)) + (:left @exp-logical) + (:right @exp-comparison)))) + + ;; @exp-comparison + + (@exp-comparison @exp-term) + (:rule (lambda (x) x)) + + (@exp-comparison @exp-term < @exp-term) + (:rule (lambda (@exp-term-left foo @exp-term-right) + (ast-node less-than-expression + (:line-col (token-line-col foo)) + (:left @exp-term-left) + (:right @exp-term-right)))) + + (@exp-comparison @exp-term == @exp-term) + (:rule (lambda (@exp-term-left foo @exp-term-right) + (ast-node equal-to-expression + (:line-col (token-line-col foo)) + (:left @exp-term-left) + (:right @exp-term-right)))) + + ;; @exp-term + + (@exp-term @exp-factor) + (:rule (lambda (x) x)) + + (@exp-term @exp-term + @exp-factor) + (:rule (lambda (@exp-term foo @exp-factor) + (ast-node add-expression + (:line-col (token-line-col foo)) + (:left @exp-term) + (:right @exp-factor)))) + + (@exp-term @exp-term - @exp-factor) + (:rule (lambda (@exp-term foo @exp-factor) + (ast-node subtract-expression + (:line-col (token-line-col foo)) + (:left @exp-term) + (:right @exp-factor)))) + + (@exp-factor @exp-factor pipe @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-or) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + + (@exp-factor @exp-factor & @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-and) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + + (@exp-factor @exp-factor ^ @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-xor) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + + ;; @exp-factor + + (@exp-factor @exp-elem) + (:rule (lambda (x) x)) + + (@exp-factor @exp-factor * @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node multiply-expression + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + + (@exp-factor @exp-factor >> @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-arith-rshift) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + + (@exp-factor @exp-factor << @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-lshift) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + + (@exp-factor @exp-factor >>> @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-rshift) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + + ;; @exp-elem + + (@exp-elem @exp-array) + (:rule (lambda (x) x)) + + (@exp-elem @exp-ref) + (:rule (lambda (x) x)) + + (@exp-elem bang @exp-elem) + (:rule (lambda (foo @exp-elem) + (ast-node not-expression + (:line-col (token-line-col foo)) + (:exp @exp-elem)))) + + (@exp-elem ~ @exp-elem) + (:rule (lambda (foo @exp-elem) + (ast-node int-unop-expression + (:op 'bit-not) + (:line-col (token-line-col foo)) + (:exp @exp-elem)))) + + ;; @exp-array + + (@exp-array @exp-ref l-brak @exp r-brak) + (:rule (lambda (@exp-ref foo-1 @exp foo-2) + (ast-node array-ref-expression + (:line-col (@ast @exp-ref :line-col)) + (:array-exp @exp-ref) + (:index-exp @exp)))) + + ;; @exp-ref + + (@exp-ref @exp-ref dot length) + (:rule (lambda (@exp-ref foo-1 foo-2) + (ast-node length-expression + (:line-col (@ast @exp-ref :line-col)) + (:exp @exp-ref)))) + + (@exp-ref @exp-ref dot @method-ident l-paren r-paren) + (:rule (lambda (@exp-ref foo-1 ident foo-2 foo-3) + (ast-node method-call-expression + (:line-col (@ast @exp-ref :line-col)) + (:object @exp-ref) + (:method-name (token-value ident)) + (:arg-list '())))) + + (@exp-ref @exp-ref dot @method-ident l-paren @exp-list r-paren) + (:rule (lambda (@exp-ref foo-1 ident foo-2 @exp-list foo-3) + (ast-node method-call-expression + (:line-col (@ast @exp-ref :line-col)) + (:object @exp-ref) + (:method-name (token-value ident)) + (:arg-list @exp-list)))) + + (@exp-ref @exp-trivial) + (:rule (lambda (x) x)) + + ;; @exp-trivial + + (@exp-trivial number) + (:rule (lambda (x) + (ast-node number-constant-expression + (:line-col (token-line-col x)) + (:value (token-value x))))) + + (@exp-trivial true) + (:rule (lambda (x) + (ast-node boolean-constant-expression + (:line-col (token-line-col x)) + (:value "true") + (:scheme-value #t)))) + + (@exp-trivial false) + (:rule (lambda (y) + (ast-node boolean-constant-expression + (:line-col (token-line-col y)) + (:value "false") + (:scheme-value #f)))) + + (@exp-trivial char-literal) + (:rule (lambda (c) + (ast-node char-constant-expression + (:line-col (token-line-col c)) + (:value (token-value c))))) + + (@exp-trivial string-literal) + (:rule (lambda (s) + (ast-node new-object-expression + (:line-col (token-line-col s)) + (:class-name "String") + (:arg-list (list + (ast-node string-constant-expression + (:line-col (token-line-col s)) + (:value (token-value s)))))))) + + (@exp-trivial ident) + (:rule (lambda (y) + (ast-node variable-expression + (:line-col (token-line-col y)) + (:ident (token-value y))))) + + (@exp-trivial this) + (:rule (lambda (y) + (ast-node this-expression + (:line-col (token-line-col y))))) + + (@exp-trivial new int l-brak @exp r-brak) + (:rule (lambda (foo-1 foo-2 foo-3 @exp foo-4) + (ast-node new-array-expression + (:line-col (token-line-col foo-1)) + (:element-type (ast-node simple-type + (:name "int"))) + (:length @exp)))) + + (@exp-trivial new char l-brak @exp r-brak) + (:rule (lambda (foo-1 foo-2 foo-3 @exp foo-4) + (ast-node new-array-expression + (:line-col (token-line-col foo-1)) + (:element-type (ast-node simple-type + (:name "char"))) + (:length @exp)))) + + (@exp-trivial new string l-brak @exp r-brak) + (:rule (lambda (foo-1 foo-2 foo-3 @exp foo-4) + (ast-node new-array-expression + (:line-col (token-line-col foo-1)) + (:element-type (ast-node user-type + (:name "String"))) + (:length @exp)))) + + (@exp-trivial new ident l-brak @exp r-brak) + (:rule (lambda (foo-1 @ident foo-3 @exp foo-4) + (ast-node new-array-expression + (:line-col (token-line-col foo-1)) + (:element-type (ast-node user-type + (:name (token-value @ident)))) + (:length @exp)))) + + (@exp-trivial new ident l-paren r-paren) + (:rule (lambda (foo-1 ident foo-2 foo-3) + (ast-node new-object-expression + (:line-col (token-line-col foo-1)) + (:class-name (token-value ident)) + (:arg-list '())))) + + + (@exp-trivial new ident l-paren @exp-list r-paren) + (:rule (lambda (foo:new ident foo:l-paren @exp-list foo:r-paren) + (ast-node new-object-expression + (:line-col (token-line-col foo:new)) + (:class-name (token-value ident)) + (:arg-list @exp-list)))) + + (@exp-trivial new string l-paren @exp-list r-paren) + (:rule (lambda (foo:new ident foo:l-paren @exp-list foo:r-paren) + (ast-node new-object-expression + (:line-col (token-line-col foo:new)) + (:class-name "String") + (:arg-list @exp-list)))) + + (@exp-trivial l-paren @exp r-paren) + (:rule (lambda (foo-1 @exp foo-2) + @exp)) + + ;; @exp-list + + (@exp-list @exp) + (:rule (lambda (x) (list x))) + + (@exp-list @exp-list comma @exp) + (:rule (lambda (x y z) (append x (list z)))) + + )) + +(define csharp-grammar + (grammar-rules-filter-productions csharp-grammar-rules)) + +(define csharp-graph (build-lr0-state-transition-graph csharp-grammar)) +(define csharp-sr-table (generate-lr0-table csharp-grammar csharp-graph csharp-grammar-rules)) +(define csharp-goto-table (generate-lr0-goto-table csharp-grammar csharp-graph)) +(define csharp-terminals (grammar-terminals csharp-grammar)) +(define csharp-nonterminals (grammar-nonterminals csharp-grammar)) +(define csharp-action-table (grammar-rules-build-action-table csharp-grammar-rules)) + +(if (file-exists? "csharp-parser.scm") + (delete-file "csharp-parser.scm")) + +(call-with-output-file "csharp-parser.scm" + (lambda (port) + (for-each + (lambda (code) (write code port) (newline port)) + `((need parse/parse) + (define action-table ,csharp-action-table) + (define (csharp-parse-input input) + (run-parse (quote ,csharp-grammar) + (quote ,(append csharp-terminals (list '$))) + (quote ,csharp-nonterminals) + (quote ,csharp-sr-table) + (quote ,csharp-goto-table) + action-table + input)) + (define (csharp-parse-port input-port) + (csharp-parse-input (read input-port))) + (define (csharp-parse-file filename) + (call-with-input-file filename + csharp-parse-port)))))) diff --git a/src/csharp-parser.scm b/src/csharp-parser.scm new file mode 100644 index 0000000..0902d97 --- /dev/null +++ b/src/csharp-parser.scm @@ -0,0 +1,5 @@ +(need parse/parse) +(define action-table (vector (lambda (x) x) (lambda (x) (ast-node program (:main-class x) (:class-list (list x)))) (lambda (x y) (ast-node program (:main-class x) (:class-list (cons x y)))) (lambda (x) (list x)) (lambda (x y) (append x (list y))) (lambda (class-1 ident-2 l-curl-3 public-4 static-5 void-6 ident-7 l-paren-8 string-9 l-brak-10 r-brak-11 ident-12 r-paren-13 l-curl-14 @statement-15 r-curl-16 r-curl-17) (ast-node class (:class-name (token-value ident-2)) (:line-col (token-line-col class-1)) (:parent #f) (:constructors (quote ())) (:potential-main-class #t) (:instance-vars (quote ())) (:static-vars (quote ())) (:methods (quote ())) (:static-methods (list (ast-node method (:name (token-value ident-7)) (:line-col (token-line-col public-4)) (:return-type (ast-node simple-type (:name "void"))) (:param-list (quote ())) (:static? #t) (:param-list-main (list (ast-node param (:type (ast-node array-type (:line-col (token-line-col string-9)) (:element-type (ast-node user-type (:line-col (token-line-col string-9)) (:name "String"))))) (:line-col (token-line-col string-9)) (:name (token-value ident-12))))) (:local-vars (quote ())) (:statements (list @statement-15))))))) (lambda (class ident @class-body) (ast-node class (:line-col (token-line-col class)) (:class-name (token-value ident)) (:parent #f) (:instance-vars (list-ref @class-body 0)) (:static-vars (list-ref @class-body 2)) (:methods (list-ref @class-body 1)) (:static-methods (list-ref @class-body 3)) (:constructors (list-ref @class-body 4)))) (lambda (class ident-name colon ident-parent @class-body) (ast-node class (:line-col (token-line-col class)) (:class-name (token-value ident-name)) (:parent (token-value ident-parent)) (:instance-vars (list-ref @class-body 0)) (:static-vars (list-ref @class-body 2)) (:methods (list-ref @class-body 1)) (:static-methods (list-ref @class-body 3)) (:constructors (list-ref @class-body 4)))) (lambda (x @class-statement-block y) (let ((vars (filter-map (lambda (x) (and (eqv? (car x) (quote var)) (cdr x))) @class-statement-block)) (s-vars (filter-map (lambda (x) (and (eqv? (car x) (quote static-var)) (cdr x))) @class-statement-block)) (methods (filter-map (lambda (x) (and (eqv? (car x) (quote method)) (not (@ast (cdr x) :static?)) (cdr x))) @class-statement-block)) (s-methods (filter-map (lambda (x) (and (eqv? (car x) (quote method)) (@ast (cdr x) :static?) (cdr x))) @class-statement-block)) (ctors (filter-map (lambda (x) (and (eqv? (quote ctor) (car x)) (cdr x))) @class-statement-block))) (list vars methods s-vars s-methods ctors))) (lambda (x y) (list (quote ()) (quote ()) (quote ()))) (lambda (x) (list x)) (lambda (x y) (append x (list y))) (lambda (@var) (cons (quote var) @var)) (lambda (@static-var) (cons (quote static-var) @static-var)) (lambda (@method) (cons (quote method) @method)) (lambda (@constructor) (cons (quote ctor) @constructor)) (lambda (v) (list v)) (lambda (@var-block @var) (append @var-block (list @var))) (lambda (@type ident s-colon) (ast-node var (:line-col (@ast @type :line-col)) (:name (token-value ident)) (:type @type))) (lambda (x @type ident s-colon) (ast-node static-var (:line-col (token-line-col x)) (:name (token-value ident)) (:type @type))) (lambda (x ident y z @method-body) (ast-node constructor (:line-col (list-ref x 2)) (:param-list (quote ())) (:static? #t) (:return-type (ast-node user-type (:name (token-value ident)))) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (--x ident --y @param-list --z @method-body) (ast-node constructor (:line-col (list-ref --x 2)) (:param-list @param-list) (:static? #t) (:return-type (ast-node user-type (:name (token-value ident)))) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (@method-start r-paren @method-body) (ast-node method (:line-col (list-ref @method-start 2)) (:name (list-ref @method-start 1)) (:param-list (quote ())) (:return-type (list-ref @method-start 0)) (:static? (list-ref @method-start 3)) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (@method-start @param-list r-paren @method-body) (ast-node method (:line-col (list-ref @method-start 2)) (:name (list-ref @method-start 1)) (:param-list @param-list) (:return-type (list-ref @method-start 0)) (:static? (list-ref @method-start 3)) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (--sasm-impl --public --static @type @method-ident --l-paren @param-list --r-paren --s-colon) (ast-node method (:sasm-impl-no-codegen #t) (:line-col (token-line-col --sasm-impl)) (:name (token-value @method-ident)) (:param-list @param-list) (:return-type @type) (:static? #t) (:local-vars (quote ())) (:statements (quote ())))) (lambda (--sasm-impl --public --static @type method-name@method-ident --l-paren @param-list --r-paren --= sasm-ident@method-ident --s-colon) (ast-node method (:sasm-impl-no-codegen #t) (:static-method-alternate-identifier (token-value sasm-ident@method-ident)) (:line-col (token-line-col --sasm-impl)) (:name (token-value method-name@method-ident)) (:param-list @param-list) (:return-type @type) (:static? #t) (:local-vars (quote ())) (:statements (quote ())))) (lambda (x y @type ident z) (list @type (token-value ident) (token-line-col x) #f)) (lambda (x y @type ident z) (list @type (token-value ident) (token-line-col x) #f)) (lambda (x y @type ident z) (list @type (token-value ident) (token-line-col x) #t)) (lambda (x) x) (lambda (x) x) (lambda (x) (list x)) (lambda (a comma b) (append a (list b))) (lambda (@type ident) (ast-node param (:line-col (@ast @type :line-col)) (:type @type) (:name (token-value ident)))) (lambda (l-curl @var-block @statement-block r-curl) (list @var-block @statement-block)) (lambda (l-curl @statement-block r-curl) (list (quote ()) @statement-block)) (lambda (l-curl r-curl) (list (quote ()) (quote ()))) (lambda (x) (list x)) (lambda (x y) (append x (list y))) (lambda (x y z) (ast-node array-type (:line-col (token-line-col x)) (:element-type (ast-node simple-type (:name "int"))))) (lambda (x y z) (ast-node array-type (:line-col (token-line-col x)) (:element-type (ast-node simple-type (:name "char"))))) (lambda (x y z) (ast-node array-type (:line-col (token-line-col x)) (:element-type (ast-node user-type (:name "String"))))) (lambda (ident y z) (ast-node array-type (:line-col (token-line-col ident)) (:element-type (ast-node user-type (:name (token-value ident)))))) (lambda (x) (ast-node simple-type (:line-col (token-line-col x)) (:name "boolean"))) (lambda (x) (ast-node simple-type (:line-col (token-line-col x)) (:name "int"))) (lambda (x) (ast-node user-type (:line-col (token-line-col x)) (:name "String"))) (lambda (x) (ast-node simple-type (:line-col (token-line-col x)) (:name "char"))) (lambda (ident) (ast-node user-type (:line-col (token-line-col ident)) (:name (token-value ident)))) (lambda (x y) (ast-node compound-statement (:line-col (token-line-col x)) (:statements (quote ())))) (lambda (x @statement-block z) (ast-node compound-statement (:line-col (token-line-col x)) (:statements @statement-block))) (lambda (if-tok l-paren @exp r-paren @statement-consequent else @statement-antecedent) (ast-node if-statement (:line-col (token-line-col if-tok)) (:condition @exp) (:consequent @statement-consequent) (:antecedent @statement-antecedent))) (lambda (while l-paren @exp r-paren @statement) (ast-node while-statement (:line-col (token-line-col while)) (:condition @exp) (:body @statement))) (lambda (x y @exp z w) (ast-node print-statement (:line-col (token-line-col x)) (:exp @exp))) (lambda (ident x @exp y) (ast-node assignment-statement (:line-col (token-line-col ident)) (:ident (token-value ident)) (:exp @exp))) (lambda (ident x @index-exp y z @value-exp w) (ast-node array-assignment-statement (:line-col (token-line-col ident)) (:ident (token-value ident)) (:index-exp @index-exp) (:value-exp @value-exp))) (lambda (r @exp s) (ast-node return-statement (:line-col (token-line-col r)) (:exp @exp))) (lambda (r s) (ast-node return-statement (:line-col (token-line-col r)))) (lambda (x) x) (lambda (x) x) (lambda (@exp-logical foo @exp-comparison) (ast-node and-expression (:line-col (token-line-col foo)) (:left @exp-logical) (:right @exp-comparison))) (lambda (x) x) (lambda (@exp-term-left foo @exp-term-right) (ast-node less-than-expression (:line-col (token-line-col foo)) (:left @exp-term-left) (:right @exp-term-right))) (lambda (@exp-term-left foo @exp-term-right) (ast-node equal-to-expression (:line-col (token-line-col foo)) (:left @exp-term-left) (:right @exp-term-right))) (lambda (x) x) (lambda (@exp-term foo @exp-factor) (ast-node add-expression (:line-col (token-line-col foo)) (:left @exp-term) (:right @exp-factor))) (lambda (@exp-term foo @exp-factor) (ast-node subtract-expression (:line-col (token-line-col foo)) (:left @exp-term) (:right @exp-factor))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-or)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-and)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-xor)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (x) x) (lambda (@exp-factor foo @exp-elem) (ast-node multiply-expression (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-arith-rshift)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-lshift)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-rshift)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (x) x) (lambda (x) x) (lambda (foo @exp-elem) (ast-node not-expression (:line-col (token-line-col foo)) (:exp @exp-elem))) (lambda (foo @exp-elem) (ast-node int-unop-expression (:op (quote bit-not)) (:line-col (token-line-col foo)) (:exp @exp-elem))) (lambda (@exp-ref foo-1 @exp foo-2) (ast-node array-ref-expression (:line-col (@ast @exp-ref :line-col)) (:array-exp @exp-ref) (:index-exp @exp))) (lambda (@exp-ref foo-1 foo-2) (ast-node length-expression (:line-col (@ast @exp-ref :line-col)) (:exp @exp-ref))) (lambda (@exp-ref foo-1 ident foo-2 foo-3) (ast-node method-call-expression (:line-col (@ast @exp-ref :line-col)) (:object @exp-ref) (:method-name (token-value ident)) (:arg-list (quote ())))) (lambda (@exp-ref foo-1 ident foo-2 @exp-list foo-3) (ast-node method-call-expression (:line-col (@ast @exp-ref :line-col)) (:object @exp-ref) (:method-name (token-value ident)) (:arg-list @exp-list))) (lambda (x) x) (lambda (x) (ast-node number-constant-expression (:line-col (token-line-col x)) (:value (token-value x)))) (lambda (x) (ast-node boolean-constant-expression (:line-col (token-line-col x)) (:value "true") (:scheme-value #t))) (lambda (y) (ast-node boolean-constant-expression (:line-col (token-line-col y)) (:value "false") (:scheme-value #f))) (lambda (c) (ast-node char-constant-expression (:line-col (token-line-col c)) (:value (token-value c)))) (lambda (s) (ast-node new-object-expression (:line-col (token-line-col s)) (:class-name "String") (:arg-list (list (ast-node string-constant-expression (:line-col (token-line-col s)) (:value (token-value s))))))) (lambda (y) (ast-node variable-expression (:line-col (token-line-col y)) (:ident (token-value y)))) (lambda (y) (ast-node this-expression (:line-col (token-line-col y)))) (lambda (foo-1 foo-2 foo-3 @exp foo-4) (ast-node new-array-expression (:line-col (token-line-col foo-1)) (:element-type (ast-node simple-type (:name "int"))) (:length @exp))) (lambda (foo-1 foo-2 foo-3 @exp foo-4) (ast-node new-array-expression (:line-col (token-line-col foo-1)) (:element-type (ast-node simple-type (:name "char"))) (:length @exp))) (lambda (foo-1 foo-2 foo-3 @exp foo-4) (ast-node new-array-expression (:line-col (token-line-col foo-1)) (:element-type (ast-node user-type (:name "String"))) (:length @exp))) (lambda (foo-1 @ident foo-3 @exp foo-4) (ast-node new-array-expression (:line-col (token-line-col foo-1)) (:element-type (ast-node user-type (:name (token-value @ident)))) (:length @exp))) (lambda (foo-1 ident foo-2 foo-3) (ast-node new-object-expression (:line-col (token-line-col foo-1)) (:class-name (token-value ident)) (:arg-list (quote ())))) (lambda (foo:new ident foo:l-paren @exp-list foo:r-paren) (ast-node new-object-expression (:line-col (token-line-col foo:new)) (:class-name (token-value ident)) (:arg-list @exp-list))) (lambda (foo:new ident foo:l-paren @exp-list foo:r-paren) (ast-node new-object-expression (:line-col (token-line-col foo:new)) (:class-name "String") (:arg-list @exp-list))) (lambda (foo-1 @exp foo-2) @exp) (lambda (x) (list x)) (lambda (x y z) (append x (list z))))) +(define (csharp-parse-input input) (run-parse (quote ((@goal @program) (@program @main-class) (@program @main-class @class-list) (@class-list @class) (@class-list @class-list @class) (@main-class class ident l-curl public static void ident l-paren string l-brak r-brak ident r-paren l-curl @statement r-curl r-curl) (@class class ident @class-body) (@class class ident colon ident @class-body) (@class-body l-curl @class-statement-block r-curl) (@class-body l-curl r-curl) (@class-statement-block @class-statement) (@class-statement-block @class-statement-block @class-statement) (@class-statement @var) (@class-statement @static-var) (@class-statement @method) (@class-statement @constructor) (@var-block @var) (@var-block @var-block @var) (@var @type ident s-colon) (@static-var static @type ident s-colon) (@constructor public ident l-paren r-paren @method-body) (@constructor public ident l-paren @param-list r-paren @method-body) (@method @method-start r-paren @method-body) (@method @method-start @param-list r-paren @method-body) (@method --sasm-impl public static @type @method-ident l-paren @param-list r-paren s-colon) (@method --sasm-impl public static @type @method-ident l-paren @param-list r-paren = ident s-colon) (@method-start virtual public @type @method-ident l-paren) (@method-start override public @type @method-ident l-paren) (@method-start public static @type @method-ident l-paren) (@method-ident ident) (@method-ident length) (@param-list @param) (@param-list @param-list comma @param) (@param @type ident) (@method-body l-curl @var-block @statement-block r-curl) (@method-body l-curl @statement-block r-curl) (@method-body l-curl r-curl) (@statement-block @statement) (@statement-block @statement-block @statement) (@type int l-brak r-brak) (@type char l-brak r-brak) (@type string l-brak r-brak) (@type ident l-brak r-brak) (@type boolean) (@type int) (@type string) (@type char) (@type ident) (@statement l-curl r-curl) (@statement l-curl @statement-block r-curl) (@statement if l-paren @exp r-paren @statement else @statement) (@statement while l-paren @exp r-paren @statement) (@statement system-console-writeline l-paren @exp r-paren s-colon) (@statement ident = @exp s-colon) (@statement ident l-brak @exp r-brak = @exp s-colon) (@statement return @exp s-colon) (@statement return s-colon) (@exp @exp-logical) (@exp-logical @exp-comparison) (@exp-logical @exp-logical && @exp-comparison) (@exp-comparison @exp-term) (@exp-comparison @exp-term < @exp-term) (@exp-comparison @exp-term == @exp-term) (@exp-term @exp-factor) (@exp-term @exp-term + @exp-factor) (@exp-term @exp-term - @exp-factor) (@exp-factor @exp-factor pipe @exp-elem) (@exp-factor @exp-factor & @exp-elem) (@exp-factor @exp-factor ^ @exp-elem) (@exp-factor @exp-elem) (@exp-factor @exp-factor * @exp-elem) (@exp-factor @exp-factor >> @exp-elem) (@exp-factor @exp-factor << @exp-elem) (@exp-factor @exp-factor >>> @exp-elem) (@exp-elem @exp-array) (@exp-elem @exp-ref) (@exp-elem bang @exp-elem) (@exp-elem ~ @exp-elem) (@exp-array @exp-ref l-brak @exp r-brak) (@exp-ref @exp-ref dot length) (@exp-ref @exp-ref dot @method-ident l-paren r-paren) (@exp-ref @exp-ref dot @method-ident l-paren @exp-list r-paren) (@exp-ref @exp-trivial) (@exp-trivial number) (@exp-trivial true) (@exp-trivial false) (@exp-trivial char-literal) (@exp-trivial string-literal) (@exp-trivial ident) (@exp-trivial this) (@exp-trivial new int l-brak @exp r-brak) (@exp-trivial new char l-brak @exp r-brak) (@exp-trivial new string l-brak @exp r-brak) (@exp-trivial new ident l-brak @exp r-brak) (@exp-trivial new ident l-paren r-paren) (@exp-trivial new ident l-paren @exp-list r-paren) (@exp-trivial new string l-paren @exp-list r-paren) (@exp-trivial l-paren @exp r-paren) (@exp-list @exp) (@exp-list @exp-list comma @exp))) (quote (class ident l-curl public static void l-paren string l-brak r-brak r-paren r-curl colon s-colon --sasm-impl = virtual override length comma int char boolean if else while system-console-writeline return && < == + - pipe & ^ * >> << >>> bang ~ dot number true false char-literal string-literal this new $)) (quote (@goal @program @class-list @main-class @class @class-body @class-statement-block @class-statement @var-block @var @static-var @constructor @method @method-start @method-ident @param-list @param @method-body @statement-block @type @statement @exp @exp-logical @exp-comparison @exp-term @exp-factor @exp-elem @exp-array @exp-ref @exp-trivial @exp-list)) (quote #(#((s . 3) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (a . #f)) #((s . 6) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 1)) #(#f (s . 7) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((s . 6) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 2)) #((r . 3) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 3)) #(#f (s . 9) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 10) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 4) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 4)) #(#f #f (s . 12) #f #f #f #f #f #f #f #f #f (s . 13) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f (s . 14) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 6) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 6)) #(#f (s . 22) #f (s . 30) (s . 25) #f #f (s . 21) #f #f #f (s . 33) #f #f (s . 31) #f (s . 28) (s . 29) #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 34) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f (s . 35) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f (s . 30) (s . 25) #f #f (s . 21) #f #f #f (s . 36) #f #f (s . 31) #f (s . 28) (s . 29) #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 10) #f (r . 10) (r . 10) #f #f (r . 10) #f #f #f (r . 10) #f #f (r . 10) #f (r . 10) (r . 10) #f #f (r . 10) (r . 10) (r . 10) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 12) #f (r . 12) (r . 12) #f #f (r . 12) #f #f #f (r . 12) #f #f (r . 12) #f (r . 12) (r . 12) #f #f (r . 12) (r . 12) (r . 12) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 38) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 44) #f #f #f #f #f #f (s . 39) #f #f #f #f #f #f #f #f #f (r . 44) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 46) #f #f #f #f #f #f (s . 40) #f #f #f #f #f #f #f #f #f (r . 46) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 45) #f #f #f #f #f #f (s . 41) #f #f #f #f #f #f #f #f #f (r . 45) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 47) #f #f #f #f #f #f (s . 42) #f #f #f #f #f #f #f #f #f (r . 47) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 43) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 43) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 13) #f (r . 13) (r . 13) #f #f (r . 13) #f #f #f (r . 13) #f #f (r . 13) #f (r . 13) (r . 13) #f #f (r . 13) (r . 13) (r . 13) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 14) #f (r . 14) (r . 14) #f #f (r . 14) #f #f #f (r . 14) #f #f (r . 14) #f (r . 14) (r . 14) #f #f (r . 14) (r . 14) (r . 14) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f (s . 44) #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f (s . 48) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f (s . 49) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 51) #f #f (s . 50) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f (s . 52) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 15) #f (r . 15) (r . 15) #f #f (r . 15) #f #f #f (r . 15) #f #f (r . 15) #f (r . 15) (r . 15) #f #f (r . 15) (r . 15) (r . 15) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 9) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 9)) #(#f #f (s . 12) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f (s . 54) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 8) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 8)) #(#f (r . 11) #f (r . 11) (r . 11) #f #f (r . 11) #f #f #f (r . 11) #f #f (r . 11) #f (r . 11) (r . 11) #f #f (r . 11) (r . 11) (r . 11) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 55) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 56) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 57) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 58) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 59) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 60) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 62) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 63) #f #f #f #f #f #f #f #f (s . 64) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (r . 31) #f #f #f #f #f #f #f #f (r . 31) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 65) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 69) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f (s . 70) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 7) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 7)) #(#f (s . 71) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 18) (r . 18) (r . 18) (r . 18) #f #f (r . 18) #f #f #f (r . 18) #f #f (r . 18) #f (r . 18) (r . 18) #f #f (r . 18) (r . 18) (r . 18) (r . 18) #f (r . 18) (r . 18) (r . 18) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 39) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 39) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 40) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 40) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 41) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 41) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 42) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 42) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 72) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 22) #f (r . 22) (r . 22) #f #f (r . 22) #f #f #f (r . 22) #f #f (r . 22) #f (r . 22) (r . 22) #f #f (r . 22) (r . 22) (r . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 75) (s . 78) #f #f #f #f (s . 21) #f #f #f (s . 83) #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 62) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (r . 33) #f #f #f #f #f #f #f #f (r . 33) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 87) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 88) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 87) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 88) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 87) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 88) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f (s . 91) #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 94) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 19) #f (r . 19) (r . 19) #f #f (r . 19) #f #f #f (r . 19) #f #f (r . 19) #f (r . 19) (r . 19) #f #f (r . 19) (r . 19) (r . 19) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 75) (s . 78) #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 16) (r . 16) #f #f #f #f (r . 16) #f #f #f #f #f #f #f #f #f #f #f #f (r . 16) (r . 16) (r . 16) (r . 16) #f (r . 16) (r . 16) (r . 16) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 47) #f #f #f #f #f #f (s . 97) #f #f #f #f #f #f (s . 98) #f #f (r . 47) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f (s . 99) #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 37) (r . 37) #f #f #f #f #f #f #f #f (r . 37) #f #f #f #f #f #f #f #f #f #f #f (r . 37) #f (r . 37) (r . 37) (r . 37) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f (s . 102) #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 104) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 105) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 106) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f (s . 127) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (r . 36) #f (r . 36) (r . 36) #f #f (r . 36) #f #f #f (r . 36) #f #f (r . 36) #f (r . 36) (r . 36) #f #f (r . 36) (r . 36) (r . 36) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 23) #f (r . 23) (r . 23) #f #f (r . 23) #f #f #f (r . 23) #f #f (r . 23) #f (r . 23) (r . 23) #f #f (r . 23) (r . 23) (r . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (r . 32) #f #f #f #f #f #f #f #f (r . 32) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 128) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (r . 29) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (r . 30) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 129) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 130) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 62) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 132) #f #f #f #f #f #f #f #f (s . 64) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 87) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 88) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (s . 134) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f (s . 135) #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 17) (r . 17) #f #f #f #f (r . 17) #f #f #f #f #f #f #f #f #f #f #f #f (r . 17) (r . 17) (r . 17) (r . 17) #f (r . 17) (r . 17) (r . 17) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f (s . 59) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (r . 35) #f (r . 35) (r . 35) #f #f (r . 35) #f #f #f (r . 35) #f #f (r . 35) #f (r . 35) (r . 35) #f #f (r . 35) (r . 35) (r . 35) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 38) (r . 38) #f #f #f #f #f #f #f #f (r . 38) #f #f #f #f #f #f #f #f #f #f #f (r . 38) #f (r . 38) (r . 38) (r . 38) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 138) #f #f #f #f #f #f (s . 98) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 48) (r . 48) #f #f #f #f #f #f #f #f (r . 48) #f #f #f #f #f #f #f #f #f #f #f (r . 48) (r . 48) (r . 48) (r . 48) (r . 48) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f (s . 139) #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 143) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 57) (r . 57) #f #f (r . 57) #f #f #f #f #f (r . 57) #f #f #f #f #f #f #f #f (s . 144) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 58) (r . 58) #f #f (r . 58) #f #f #f #f #f (r . 58) #f #f #f #f #f #f #f #f (r . 58) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 60) (r . 60) #f #f (r . 60) #f #f #f #f #f (r . 60) #f #f #f #f #f #f #f #f (r . 60) (s . 147) (s . 148) (s . 145) (s . 146) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 63) (r . 63) #f #f (r . 63) #f #f #f #f #f (r . 63) #f #f #f #f #f #f #f #f (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (s . 149) (s . 150) (s . 151) (s . 152) (s . 153) (s . 154) (s . 155) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 69) (r . 69) #f #f (r . 69) #f #f #f #f #f (r . 69) #f #f #f #f #f #f #f #f (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 74) (r . 74) #f #f (r . 74) #f #f #f #f #f (r . 74) #f #f #f #f #f #f #f #f (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 156) (r . 75) (r . 75) #f #f (r . 75) #f #f #f #f #f (r . 75) #f #f #f #f #f #f #f #f (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) #f #f (s . 157) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 82) (r . 82) (r . 82) #f #f (r . 82) #f #f #f #f #f (r . 82) #f #f #f #f #f #f #f #f (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) #f #f (r . 82) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 83) (r . 83) (r . 83) #f #f (r . 83) #f #f #f #f #f (r . 83) #f #f #f #f #f #f #f #f (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) #f #f (r . 83) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 84) (r . 84) (r . 84) #f #f (r . 84) #f #f #f #f #f (r . 84) #f #f #f #f #f #f #f #f (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) #f #f (r . 84) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 85) (r . 85) (r . 85) #f #f (r . 85) #f #f #f #f #f (r . 85) #f #f #f #f #f #f #f #f (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) #f #f (r . 85) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 86) (r . 86) (r . 86) #f #f (r . 86) #f #f #f #f #f (r . 86) #f #f #f #f #f #f #f #f (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) #f #f (r . 86) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 87) (r . 87) (r . 87) #f #f (r . 87) #f #f #f #f #f (r . 87) #f #f #f #f #f #f #f #f (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) #f #f (r . 87) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 88) (r . 88) (r . 88) #f #f (r . 88) #f #f #f #f #f (r . 88) #f #f #f #f #f #f #f #f (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) #f #f (r . 88) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 89) (r . 89) (r . 89) #f #f (r . 89) #f #f #f #f #f (r . 89) #f #f #f #f #f #f #f #f (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) #f #f (r . 89) #f #f #f #f #f #f #f #f) #(#f (s . 161) #f #f #f #f #f (s . 160) #f #f #f #f #f #f #f #f #f #f #f #f (s . 158) (s . 159) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (r . 56) (r . 56) #f #f #f #f #f #f #f #f (r . 56) #f #f #f #f #f #f #f #f #f #f #f (r . 56) (r . 56) (r . 56) (r . 56) (r . 56) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 26) #f #f #f #f #f (r . 26) #f #f (r . 26) #f #f #f #f #f #f #f #f #f (r . 26) (r . 26) (r . 26) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 27) #f #f #f #f #f (r . 27) #f #f (r . 27) #f #f #f #f #f #f #f #f #f (r . 27) (r . 27) (r . 27) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 28) #f #f #f #f #f (r . 28) #f #f (r . 28) #f #f #f #f #f #f #f #f #f (r . 28) (r . 28) (r . 28) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 20) #f (r . 20) (r . 20) #f #f (r . 20) #f #f #f (r . 20) #f #f (r . 20) #f (r . 20) (r . 20) #f #f (r . 20) (r . 20) (r . 20) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 62) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 166) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 167) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 34) #f (r . 34) (r . 34) #f #f (r . 34) #f #f #f (r . 34) #f #f (r . 34) #f (r . 34) (r . 34) #f #f (r . 34) (r . 34) (r . 34) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 168) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 169) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (r . 49) (r . 49) #f #f #f #f #f #f #f #f (r . 49) #f #f #f #f #f #f #f #f #f #f #f (r . 49) (r . 49) (r . 49) (r . 49) (r . 49) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 170) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 171) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 172) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 55) (r . 55) #f #f #f #f #f #f #f #f (r . 55) #f #f #f #f #f #f #f #f #f #f #f (r . 55) (r . 55) (r . 55) (r . 55) (r . 55) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 87) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 186) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 188) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 189) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 191) #f (s . 190) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 193) #f (s . 192) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 194) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 76) (r . 76) #f #f (r . 76) #f #f #f #f #f (r . 76) #f #f #f #f #f #f #f #f (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 77) (r . 77) #f #f (r . 77) #f #f #f #f #f (r . 77) #f #f #f #f #f #f #f #f (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 21) #f (r . 21) (r . 21) #f #f (r . 21) #f #f #f (r . 21) #f #f (r . 21) #f (r . 21) (r . 21) #f #f (r . 21) (r . 21) (r . 21) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 22) #f #f #f #f #f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 196) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 197) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 53) (r . 53) #f #f #f #f #f #f #f #f (r . 53) #f #f #f #f #f #f #f #f #f #f #f (r . 53) (r . 53) (r . 53) (r . 53) (r . 53) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 200) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 59) (r . 59) #f #f (r . 59) #f #f #f #f #f (r . 59) #f #f #f #f #f #f #f #f (r . 59) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 64) (r . 64) #f #f (r . 64) #f #f #f #f #f (r . 64) #f #f #f #f #f #f #f #f (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (s . 149) (s . 150) (s . 151) (s . 152) (s . 153) (s . 154) (s . 155) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 65) (r . 65) #f #f (r . 65) #f #f #f #f #f (r . 65) #f #f #f #f #f #f #f #f (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (s . 149) (s . 150) (s . 151) (s . 152) (s . 153) (s . 154) (s . 155) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 61) (r . 61) #f #f (r . 61) #f #f #f #f #f (r . 61) #f #f #f #f #f #f #f #f (r . 61) #f #f (s . 145) (s . 146) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 62) (r . 62) #f #f (r . 62) #f #f #f #f #f (r . 62) #f #f #f #f #f #f #f #f (r . 62) #f #f (s . 145) (s . 146) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 66) (r . 66) #f #f (r . 66) #f #f #f #f #f (r . 66) #f #f #f #f #f #f #f #f (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 67) (r . 67) #f #f (r . 67) #f #f #f #f #f (r . 67) #f #f #f #f #f #f #f #f (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 68) (r . 68) #f #f (r . 68) #f #f #f #f #f (r . 68) #f #f #f #f #f #f #f #f (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 70) (r . 70) #f #f (r . 70) #f #f #f #f #f (r . 70) #f #f #f #f #f #f #f #f (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 71) (r . 71) #f #f (r . 71) #f #f #f #f #f (r . 71) #f #f #f #f #f #f #f #f (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 72) (r . 72) #f #f (r . 72) #f #f #f #f #f (r . 72) #f #f #f #f #f #f #f #f (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 73) (r . 73) #f #f (r . 73) #f #f #f #f #f (r . 73) #f #f #f #f #f #f #f #f (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 201) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (r . 30) #f (r . 79) (r . 79) (r . 79) #f #f (r . 79) #f #f #f #f #f (r . 79) #f #f #f #f #f #f #f #f (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) #f #f (r . 79) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 202) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f (s . 209) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f #f #f #f #f #f #f #f (r . 97) (r . 97) (r . 97) #f #f (r . 97) #f #f #f #f #f (r . 97) #f #f #f #f #f #f #f #f (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) (r . 97) #f #f (r . 97) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 211) #f #f #f #f #f #f #f #f (s . 64) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 212) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 214) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 51) (r . 51) #f #f #f #f #f #f #f #f (r . 51) #f #f #f #f #f #f #f #f #f #f #f (r . 51) (r . 51) (r . 51) (r . 51) (r . 51) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 52) (r . 52) #f #f #f #f #f #f #f #f (r . 52) #f #f #f #f #f #f #f #f #f #f #f (r . 52) (r . 52) (r . 52) (r . 52) (r . 52) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 78) (r . 78) #f #f (r . 78) #f #f #f #f #f (r . 78) #f #f #f #f #f #f #f #f (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f (s . 215) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f #f #f #f #f #f #f #f #f (s . 217) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 218) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 219) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 220) #f #f #f #f #f #f #f #f (s . 221) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (r . 98) #f #f #f #f #f #f #f #f (r . 98) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 222) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 94) (r . 94) (r . 94) #f #f (r . 94) #f #f #f #f #f (r . 94) #f #f #f #f #f #f #f #f (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) (r . 94) #f #f (r . 94) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 223) #f #f #f #f #f #f #f #f (s . 221) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 224) #f (s . 225) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 226) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 227) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 80) (r . 80) (r . 80) #f #f (r . 80) #f #f #f #f #f (r . 80) #f #f #f #f #f #f #f #f (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) #f #f (r . 80) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 229) #f #f #f #f #f #f #f #f (s . 221) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 90) (r . 90) (r . 90) #f #f (r . 90) #f #f #f #f #f (r . 90) #f #f #f #f #f #f #f #f (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) #f #f (r . 90) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 91) (r . 91) (r . 91) #f #f (r . 91) #f #f #f #f #f (r . 91) #f #f #f #f #f #f #f #f (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) #f #f (r . 91) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 92) (r . 92) (r . 92) #f #f (r . 92) #f #f #f #f #f (r . 92) #f #f #f #f #f #f #f #f (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) #f #f (r . 92) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 96) (r . 96) (r . 96) #f #f (r . 96) #f #f #f #f #f (r . 96) #f #f #f #f #f #f #f #f (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) (r . 96) #f #f (r . 96) #f #f #f #f #f #f #f #f) #(#f (s . 121) #f #f #f #f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 125) (s . 126) #f (s . 116) (s . 117) (s . 118) (s . 119) (s . 120) (s . 122) (s . 123) #f) #(#f #f #f #f #f #f #f #f (r . 93) (r . 93) (r . 93) #f #f (r . 93) #f #f #f #f #f (r . 93) #f #f #f #f #f #f #f #f (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) (r . 93) #f #f (r . 93) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 95) (r . 95) (r . 95) #f #f (r . 95) #f #f #f #f #f (r . 95) #f #f #f #f #f #f #f #f (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) (r . 95) #f #f (r . 95) #f #f #f #f #f #f #f #f) #(#f (r . 24) #f (r . 24) (r . 24) #f #f (r . 24) #f #f #f (r . 24) #f #f (r . 24) #f (r . 24) (r . 24) #f #f (r . 24) (r . 24) (r . 24) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 231) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 232) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 54) (r . 54) #f #f #f #f #f #f #f #f (r . 54) #f #f #f #f #f #f #f #f #f #f #f (r . 54) (r . 54) (r . 54) (r . 54) (r . 54) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 50) (r . 50) #f #f #f #f #f #f #f #f (r . 50) #f #f #f #f #f #f #f #f #f #f #f (r . 50) (r . 50) (r . 50) (r . 50) (r . 50) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 81) (r . 81) (r . 81) #f #f (r . 81) #f #f #f #f #f (r . 81) #f #f #f #f #f #f #f #f (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) #f #f (r . 81) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (r . 99) #f #f #f #f #f #f #f #f (r . 99) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f (s . 233) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 101) (s . 78) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 79) #f (s . 80) (s . 81) (s . 82) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 25) #f (r . 25) (r . 25) #f #f (r . 25) #f #f #f (r . 25) #f #f (r . 25) #f (r . 25) (r . 25) #f #f (r . 25) (r . 25) (r . 25) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f (s . 235) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f (s . 236) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 5) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 5)))) (quote #(#(#f (g . 1) #f (g . 2) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (g . 4) #f (g . 5) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f (g . 8) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f (g . 11) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (g . 15) (g . 16) #f (g . 17) (g . 24) (g . 32) (g . 26) (g . 27) #f #f #f #f #f (g . 18) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (g . 37) #f (g . 17) (g . 24) (g . 32) (g . 26) (g . 27) #f #f #f #f #f (g . 18) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 43) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 45) (g . 46) #f #f (g . 47) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f (g . 53) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 61) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 66) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 67) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 68) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (g . 73) (g . 74) #f #f #f #f #f #f #f #f (g . 76) (g . 18) (g . 77) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 84) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 85) #f #f (g . 47) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 86) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 89) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 90) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 92) (g . 46) #f #f (g . 47) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 93) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (g . 96) #f #f #f #f #f #f #f #f (g . 95) (g . 18) (g . 77) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 100) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 103) #f (g . 77) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 107) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 131) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 133) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 100) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 136) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 137) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 100) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 140) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 141) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 142) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 162) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 163) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 164) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 165) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 136) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 173) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 174) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 175) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 176) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 177) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 178) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 179) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 180) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 181) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 182) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 183) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 184) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 185) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 187) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 195) (g . 46) #f #f (g . 47) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 198) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 199) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 203) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 204) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 205) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 207) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) (g . 206)) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 208) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 207) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) (g . 210)) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 213) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 207) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) (g . 216)) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 228) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 230) (g . 108) (g . 109) (g . 110) (g . 111) (g . 112) (g . 113) (g . 114) (g . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 234) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f))) action-table input)) +(define (csharp-parse-port input-port) (csharp-parse-input (read input-port))) +(define (csharp-parse-file filename) (call-with-input-file filename csharp-parse-port)) diff --git a/src/csharp-scanner.scm b/src/csharp-scanner.scm new file mode 100644 index 0000000..d2f4d7b --- /dev/null +++ b/src/csharp-scanner.scm @@ -0,0 +1,4 @@ +(need regex/dfa) +(need regex/genlex) +(define csharp-lexer-dfa (build-fast-dfa (quote 721) (quote #(#t #t #t #t #t #t #t #t #t #t #t #f #f #f #f #f #f #t #t #t #t #t #f #f #f #t #t #f #f #t #t #t #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #f #f #f #f #t #t #f #f #t #t)) (quote #(#(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 0 0 0 0 0 0 0 0 0 0 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 1 #f #f #f #f #f #f #f #f 5 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 4 #f #f #f #f #f #f #f #f 7 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 0 0 0 0 0 0 0 0 0 0 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 1 #f #f #f #f #f #f #f #f 5 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 4 #f #f #f #f #f #f #f #f 7 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 21 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 21 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 21 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 21 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f 13 #f 13 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f 13 #f 13 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 21 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 26 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f 23 #f 23 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 26 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 27 27 27 27 #f 27 27 #f 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 24 27 27 27 #f 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 31 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 32 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 33 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 34 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 35 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 36 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 37 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 38 #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 39 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 40 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 41 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 42 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 43 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 44 #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 45 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 46 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 47 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 48 #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 49 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 50 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 51 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 52 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 53 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 55 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 57 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 58 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 56 179 179 59 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 60 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 62 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 63 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 65 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 66 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 64 179 179 179 179 179 179 179 179 179 67 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 77 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 78 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 80 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 82 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 84 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 86 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 87 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 88 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 89 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 90 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 91 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 92 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 94 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 95 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 96 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 98 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 99 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 100 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 101 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 103 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 104 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 105 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 106 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 107 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 109 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 110 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 111 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 114 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 113 179 179 179 179 179 179 179 115 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 121 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 122 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 123 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 124 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 125 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 127 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 128 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 126 179 179 179 179 179 129 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 131 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 132 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 133 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 134 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 135 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 141 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 142 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 144 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 145 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 146 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 147 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 148 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 150 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 151 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 152 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 154 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 155 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 156 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 157 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 153 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 159 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 160 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 161 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 158 162 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 164 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 165 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 167 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 168 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 169 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 166 179 179 179 170 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 282 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 283 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 284 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 285 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 286 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 287 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 288 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 289 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 179 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 290 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f #f #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f 291 #f 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 293 293 #f #f 293 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 293 293 293 293 #f 293 293 293 293 293 713 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 #f 293 293 293 #f 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 294 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 294 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 296 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 296 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 296 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 296 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 302 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 302 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 302 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 302 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f 305 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f 305 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f 305 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f 305 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 308 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 308 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 308 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 308 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f 314 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f 314 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f 314 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f 314 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 319 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 319 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 319 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 319 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 322 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 322 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 322 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 322 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 325 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 325 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 325 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 325 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 331 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 331 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 331 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 331 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 334 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 334 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 334 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 334 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 337 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 337 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 337 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 337 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 342 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 342 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 342 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 342 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 345 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 345 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 345 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 345 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 348 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 348 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 348 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 348 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 354 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 354 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 354 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 354 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 357 #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 357 #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 357 #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 357 #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 360 #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 360 #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 360 #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 360 #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 365 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 365 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 365 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 365 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 371 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 371 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 371 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 371 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 373 #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 373 #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 373 #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 373 #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 376 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 376 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 376 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 376 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 382 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 382 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 382 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 382 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 387 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 387 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 387 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 387 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 390 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 390 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 390 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 390 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 393 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 393 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 393 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 393 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 399 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 399 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 399 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 399 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 402 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 402 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 402 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 402 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 405 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 405 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 405 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 405 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 410 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 410 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 410 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 410 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 413 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 413 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 413 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 413 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 416 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 416 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 416 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 416 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 421 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 421 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 421 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 421 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 427 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 427 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 427 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 427 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 429 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 429 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 429 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 429 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 432 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 432 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 432 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 432 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 438 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 438 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 438 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 438 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 441 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 441 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 441 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 441 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 444 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 444 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 444 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 444 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 450 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 450 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 450 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 450 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 455 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 455 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 455 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 455 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 458 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 458 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 458 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 458 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 461 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 461 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 461 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 461 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 466 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 466 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 466 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 466 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 469 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 469 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 469 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 469 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 472 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 472 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 472 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 472 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 477 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 477 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 477 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 477 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 483 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 483 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 483 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 483 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 486 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 486 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 486 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 486 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 489 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 489 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 489 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 489 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 495 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 495 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 495 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 495 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 497 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 497 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 497 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 497 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 500 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 500 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 500 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 500 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 506 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 506 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 506 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 506 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 509 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 509 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 509 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 509 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 512 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 512 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 512 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 512 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 518 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 518 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 518 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 518 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 523 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 523 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 523 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 523 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 526 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 526 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 526 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 526 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 529 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 529 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 529 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 529 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 535 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 535 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 535 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 535 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 538 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 538 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 538 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 538 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 541 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 541 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 541 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 541 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 546 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 546 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 546 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 546 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 549 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 549 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 549 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 549 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 552 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 552 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 552 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 552 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 557 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 557 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 557 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 557 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 563 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 563 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 563 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 563 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 565 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 565 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 565 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 565 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 568 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 568 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 568 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 568 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 574 #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 574 #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 574 #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 574 #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 577 #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 577 #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 577 #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 577 #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 580 #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 580 #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 580 #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 580 #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 586 #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 586 #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 586 #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 586 #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 591 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 591 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 591 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 591 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 594 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 594 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 594 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 594 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 597 #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 597 #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 597 #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 597 #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 602 #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 602 #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 602 #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 602 #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 605 #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 605 #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 605 #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 605 #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 608 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 608 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 608 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 608 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 613 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 613 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 613 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 613 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 619 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 619 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 619 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 619 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 622 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 622 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 622 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 622 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 625 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 625 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 625 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 625 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 631 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 631 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 631 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 631 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 633 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 633 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 633 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 633 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 636 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 636 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 636 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 636 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 642 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 642 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 642 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 642 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 647 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 647 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 647 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 647 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 650 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 650 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 650 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 650 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 653 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 653 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 653 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 653 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 658 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 658 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 658 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 658 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 661 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 661 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 661 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 661 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 664 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 664 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 664 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 664 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 676 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 687 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 670 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 294 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 690 690 #f #f 690 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 690 690 690 690 #f 690 690 690 690 690 294 690 690 690 690 699 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f 690 690 690 #f 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 690 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 293 293 #f #f 293 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 293 293 293 293 #f 293 293 293 293 293 713 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 #f 293 293 293 #f 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 293 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 715 716 #f #f 715 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 715 715 715 715 #f 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 #f 715 715 715 #f 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 715 716 #f #f 715 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 715 715 715 715 #f 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 #f 715 715 715 #f 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 715 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 714 #f #f #f #f 718 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 720 720 #f #f 720 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 720 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 720 720 #f #f 720 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 720 30 22 #f #f #f 83 28 140 139 74 76 29 75 73 719 9 9 9 9 9 9 9 9 9 9 118 117 81 85 79 72 #f 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 54 10 10 10 10 10 10 10 120 #f 119 69 292 #f 10 112 171 10 97 61 10 10 116 10 10 149 10 143 93 136 10 108 163 68 10 130 102 10 10 10 138 71 137 70 #f) #() #()))) (quote #(number number number number number number number number number number ident #f #f #f #f #f #f string-literal string-literal string-literal string-literal string-literal #f #f #f char-literal char-literal #f #f comma bang system-console-writeline #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f ident ident ident ident ident ident fail ident false ident ident ident ident this ident ident true ident ident ident ^ ~ pipe ? dot * - + >>> >> > << < && & == = override ident ident ident ident ident ident ident else ident ident ident while ident ident ident ident return ident ident ident ident ident boolean ident ident ident if int ident ident s-colon colon r-brak l-brak virtual ident ident ident ident ident void ident ident ident public ident ident ident ident ident r-curl l-curl r-paren l-paren new ident ident length ident ident ident ident ident string ident ident ident static ident ident ident ident super ident ident ident ident char ident ident class ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident --sasm-impl ident ident ident ident ident ident ident ident ident ident #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* *comment* #f #f #f #f *comment* *comment* #f #f *whitespace* *whitespace*)))) +(define csharp-lexically-analyze (let ((main-dfa csharp-lexer-dfa)) (lambda (input-port) (run-generated-lexer main-dfa (quote (*whitespace* *comment*)) input-port)))) diff --git a/src/csharp-tokens.scm b/src/csharp-tokens.scm new file mode 100644 index 0000000..535cbdf --- /dev/null +++ b/src/csharp-tokens.scm @@ -0,0 +1,127 @@ +;; csharp-lex.scm +;; + +(need regex/regex) +(need regex/genlex) +(need util/list) + +;; Some basic definitions to aid in building regular expressions + +(define (chars string) + string) + +(define (chars-append . args) + (apply string-append args)) + +(define (chars-without chars exclude) + (list->string (filter (lambda (char) (not (strchr exclude char))) + (string->list chars)))) + +(define alpha (chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")) +(define numeric (chars "0123456789")) +(define whitespace (chars "\r\t\n ")) +(define special (chars "~!@#%^&*()-=+{[]}|:;'<>,.?/_\"")) +(define ident-start (chars-append alpha (chars "_"))) +(define ident (chars-append ident-start numeric)) +(define string-chars (chars-append alpha numeric (chars-without special "\"") + (chars " "))) +(define slashslash-comment-chars (chars-append alpha numeric special (chars-without whitespace "\n"))) +(define slashstar-comment-chars (chars-append alpha numeric (chars-without special "*/") whitespace)) +(define integer-pattern `(& (+ (@ ,numeric)) (^ (: #\u #\U #\l #\L)))) +(define identifier-pattern `(& (@ ,ident-start) (* (@ ,ident)))) +(define string-pattern `(& #\" + (* (: (& #\\ (@ "0nrt\"\\")) + (@ ,string-chars))) + #\")) +(define char-pattern `(& #\' + (: (@ ,(chars-append alpha numeric (chars " ") + (chars-without special "'"))) + (& #\\ (@ "0nrt\\'"))) + #\')) +(define slashstar-comment-pattern `(& #\/ #\* + (* (@ ,(chars-append slashstar-comment-chars (chars "/")))) + #\* + (* #\*) + (* (& (@ ,slashstar-comment-chars) + (* ,(chars-append slashstar-comment-chars (chars "/"))) + #\* + (* #\*))) + #\/)) + +(define tokens + `((*whitespace* (* (@ ,whitespace))) + (*comment* (& #\/ #\/ (* (@ ,slashslash-comment-chars)) #\newline)) + (*comment* ,slashstar-comment-pattern) + (--sasm-impl "__sasm_impl") + (class "class") + (super "super") + (length "length") + (new "new") + (l-paren "(") + (r-paren ")") + (l-curl "{") + (r-curl "}") + (public "public") + (static "static") + (void "void") + (l-brak "[") + (r-brak "]") + (colon ":") + (s-colon ";") + (int "int") + (string "string") + (char "char") + (boolean "bool") + (return "return") + (if "if") + (while "while") + (else "else") + (virtual "virtual") + (override "override") + (= "=") + (&& "&&") + (< "<") + (== "==") + (> ">") + (+ "+") + (- "-") + (* "*") + (dot ".") + (? "?") + (>>> ">>>") + (>> ">>") + (<< "<<") + (pipe "|") + (& "&") + (~ "~") + (^ "^") + (true "true") + (this "this") + (false "false") + (system-console-writeline "System.Console.WriteLine") + (fail "fail") + (bang "!") + (comma ",") + (char-literal ,char-pattern) + (string-literal ,string-pattern) + (ident ,identifier-pattern) + (number ,integer-pattern) + )) + +(define csharp-lexer (generate-lexer tokens + '(*whitespace* *comment*))) + +(define lexer-filename "csharp-scanner.scm") + +(define (main) + (if (file-exists? lexer-filename) + (delete-file lexer-filename)) + + (call-with-output-file lexer-filename + (lambda (port) + (write-lexer csharp-lexer + 'csharp-lexer-dfa + 'csharp-lexically-analyze + port)))) + +(main) diff --git a/src/env-selfbld.cmd b/src/env-selfbld.cmd new file mode 100644 index 0000000..45105e6 --- /dev/null +++ b/src/env-selfbld.cmd @@ -0,0 +1,4 @@ +set SCHEMEC=out\bootstrap\schemec.exe +set SASMOPT=out\bootstrap\sasm-opt.exe +set SASMC=out\bootstrap\sasm.exe +set OUTDIR=out\selfbld diff --git a/src/env.cmd b/src/env.cmd new file mode 100644 index 0000000..67c4944 --- /dev/null +++ b/src/env.cmd @@ -0,0 +1,10 @@ +rem configure paths to TinyScheme interpreter as bootstrap +set TINYSCHEMEINIT=%~dp0..\bootstrap\tinyscheme-1.41\init.scm +set SCHEME=%~dp0..\bootstrap\tinyscheme-1.41\scheme.exe -1 + +rem configure bootstrap tools on top of the interpreter +set SCHEMEC=%SCHEME% out\scheme-compiler-flat-ts.scm +set SASMOPT=%SCHEME% out\sasm-opt-flat-ts.scm +set SASMC=%SCHEME% out\sasm-flat-ts.scm + +set OUTDIR=out\bootstrap diff --git a/src/fix-spimout.scm b/src/fix-spimout.scm new file mode 100644 index 0000000..d5bffe0 --- /dev/null +++ b/src/fix-spimout.scm @@ -0,0 +1,16 @@ +(need util/io) +(need util/string) + +(define *input-port* (open-input-file (vector-ref *argv* 1))) +(define *output-port* (open-output-file (vector-ref *argv* 2))) + +(for-each (lambda (x) + (define prefix "@SYSTEM-OUT-PRINTLN ") + (if (string-starts-with? x prefix) + (begin (display (substring x (string-length prefix) (string-length x)) + *output-port*) + (newline *output-port*)))) + (read-lines-fully *input-port*)) + +(close-output-port *output-port*) +(close-input-port *input-port*) diff --git a/src/generate-java-lexer.scm b/src/generate-java-lexer.scm new file mode 100644 index 0000000..fe415e7 --- /dev/null +++ b/src/generate-java-lexer.scm @@ -0,0 +1,27 @@ +;; generate-java-lexer.scm +;; +;; adapted from minijava-tokens.scm +;; +;; + +(need regex/regex) +(need regex/genlex) +(need util/list) +(need minijava-lexer-java) + +(define lexer-filename "scp/frontend/java/lexer/JavaLexerData.java") + +(define (main) + (if (file-exists? lexer-filename) + (delete-file lexer-filename)) + + (call-with-output-file lexer-filename + (lambda (port) + (write-java-lexer-from-dfa minijava-lexer-dfa + "scp.frontend.java.lexer" + #f + "final" + "JavaLexerData" + port)))) + +(main) diff --git a/src/go.cmd b/src/go.cmd new file mode 100644 index 0000000..4ce8ff7 --- /dev/null +++ b/src/go.cmd @@ -0,0 +1,37 @@ +@setlocal +@echo off + +call env.cmd +if not exist ..\bootstrap\tinyscheme-1.41\scheme.exe goto :missing + +echo ########################################################################## +echo ## Generating .dep files +echo ########################################################################## + +rem generate dependencies +set NEEDC=%scheme% needc-ts.scm +%NEEDC% --makefile-mode --windows-mode --output sasm.dep sasm +%NEEDC% --makefile-mode --windows-mode --output sasm-opt.dep sasm-opt +%NEEDC% --makefile-mode --windows-mode --output scheme-compiler.dep scheme-compiler +%NEEDC% --makefile-mode --windows-mode --output java-compiler.dep java-compiler + +echo ########################################################################## +echo ## Scheme and SASM Tool Bootstrap +echo ########################################################################## + +call make -f bootstrap.win32.makefile +if not exist out\bootstrap\sasm.exe exit /b 1 +if not exist out\bootstrap\sasm-opt.exe exit /b 1 +if not exist out\bootstrap\schemec.exe exit /b 1 + +echo ########################################################################## +echo ## Scheme and SASM Self-Build +echo ########################################################################## + +call make -f selfbld.win32.makefile +exit /b %errorlevel% + +:missing +echo Unable to find ..\bootstrap\tinyscheme-1.41\scheme.exe +echo Run 'make' in ..\bootstrap\tinyscheme-1.41 first, as a one-time step +exit /b 1 diff --git a/src/java-compiler-ts.scm b/src/java-compiler-ts.scm new file mode 100644 index 0000000..2e48363 --- /dev/null +++ b/src/java-compiler-ts.scm @@ -0,0 +1,8 @@ +;; java-compiler-ts.scm +;; +;; TinyScheme bootstrap for the minijava compiler. + +(need compat/tinyscheme) +(need scheme/tag) +(need scheme/genproc) +(need java-compiler) diff --git a/src/java-compiler.dep b/src/java-compiler.dep new file mode 100644 index 0000000..1b95b5c --- /dev/null +++ b/src/java-compiler.dep @@ -0,0 +1,33 @@ +# generated by needc 01-20-2019 0.3 + +deps_of_java_compiler=\ + util/counting.scm \ + algo/bsearch.scm \ + util/list.scm \ + util/string.scm \ + util/vector.scm \ + regex/fsm.scm \ + regex/fast-dfa.scm \ + algo/quicksort.scm \ + regex/dfa.scm \ + regex/nfa.scm \ + util/format.scm \ + scheme/tag.scm \ + regex/compile.scm \ + regex/regex.scm \ + scheme/genproc.scm \ + regex/genlex.scm \ + parse/parse.scm \ + ast.scm \ + pat/pat.scm \ + sasm/sasm-insn.scm \ + minijava-lexer.scm \ + minijava-parser.scm \ + types.scm \ + symtab.scm \ + typechk.scm \ + tailcall.scm \ + codegen.scm \ + sasm/sasm-codegen.scm \ + # 28 dependencies listed + diff --git a/src/java-compiler.scm b/src/java-compiler.scm new file mode 100644 index 0000000..982989a --- /dev/null +++ b/src/java-compiler.scm @@ -0,0 +1,103 @@ +(need parse/parse) +(need regex/dfa) +(need regex/genlex) + +(need ast) +(need minijava-lexer) +(need minijava-parser) +(need types) +(need symtab) +(need typechk) +(need tailcall) +(need codegen) +(need sasm/sasm-codegen) + +(define *output-port* (current-output-port)) + +(define (emit-code context code) + (sasm-pretty-print code *output-port*) + (newline *output-port*)) + +(define (emit-statement ast-node code) + ;; why doesn't this do anything? it is still used + ;; by codegen.scm, but it doesn't look like it is actually doing + ;; anything. + code) + +(define (parse-port port) + (let ((lex (minijava-lexically-analyze port))) + (and lex + (minijava-parse-input lex)))) + +(define (run-typecheck ast) + (let ((symtab (build-symtab ast))) + (and symtab + (let ((typecheck-result (typecheck ast symtab))) + (if (not typecheck-result) + (exit 1)) + (and typecheck-result + symtab))))) + +(define (run-codegen-analysis ast env) + (mark-tailcalls ast env) + #t) + +(define (compile port) + (let ((ast (parse-port port))) + (if (not ast) + (exit 1)) + (and ast + (let ((env (run-typecheck ast))) + (and env + (run-codegen-analysis ast env) + (codegen ast env (tag 'context '()))))))) + +(define (merge-programs program-a program-b) + (define (choose-main main-a main-b) + (cond (main-b main-b) + (main-a main-a) + (else #f))) + (define (get-main) + (choose-main (and (ast-node-attr? program-a ':main-class) (@ast program-a :main-class)) + (and (ast-node-attr? program-b ':main-class) (@ast program-b :main-class)))) + (ast-node program + (:main-class (get-main)) + (:class-list (append (@ast program-a :class-list) + (@ast program-b :class-list))))) + +(define (merge-multiple-programs list) + (accum merge-programs (car list) (cdr list))) + +(define (compile-multiple main-class programs) + (let ((asts (map (lambda (file) (call-with-input-file file parse-port)) programs))) + (and (all? (lambda (x) x) asts) + (let* ((master-program (merge-multiple-programs asts)) + (env (run-typecheck master-program))) + (and env + (run-codegen-analysis master-program env) + (codegen master-program env (tag 'context `((main-class ,main-class))))))))) + +(cond ((= 1 (vector-length *argv*)) + (compile (current-input-port))) + ((= 2 (vector-length *argv*)) + (call-with-input-file (vector-ref *argv* 1) compile)) + ((and (>= (vector-length *argv*) 3) + (starts-with? (vector-ref *argv* 1) "--main=")) + (let ((main-class-name (string-strip-prefix (vector-ref *argv* 1) + "--main=")) + (args + (filter (lambda (arg) + (cond + ((starts-with? arg "--out=") + (set! *output-port* + (open-output-file (string-strip-prefix arg + "--out="))) + #f) + (else #t))) + (cddr (vector->list *argv*))))) + (compile-multiple main-class-name args))) + (else + (error "Invalid command line " *argv*))) + +(if (not (eq? *output-port* (current-output-port))) + (close-output-port *output-port*)) diff --git a/src/lexer.scm b/src/lexer.scm new file mode 100644 index 0000000..969df43 --- /dev/null +++ b/src/lexer.scm @@ -0,0 +1,38 @@ +(need regex/dfa) +(need regex/genlex) +(load "minijava-lexer.scm") + +(let ((start-time (current-seconds))) + (let ((res (minijava-lexically-analyze (current-input-port)))) + (let ((end-time (current-seconds))) + (if res + (begin + (display "(") + (newline) + (for-each (lambda (obj) + (write obj) + (newline)) + res) + (display ")") + (newline) + (let ((elapsed-time (- end-time start-time))) + (define (present-number num) + (number->string (/ (exact->inexact (ceiling (* num 100))) 100))) + (define (present-ratio numerator denominator) + (if (zero? denominator) + (string-append (number->string numerator) + "/" + (number->string denominator)) + (present-number (/ numerator denominator)))) + (for-each display + (list ";; elapsed time " + (present-number elapsed-time) + "s\n" + ";; " + (length res) + " (" + (present-number (length res)) + ") tokens\n" + ";; " + (present-ratio (length res) elapsed-time) + " tokens/s\n")))))))) diff --git a/src/minijava-grammar.scm b/src/minijava-grammar.scm new file mode 100644 index 0000000..4ab035c --- /dev/null +++ b/src/minijava-grammar.scm @@ -0,0 +1,1193 @@ +(need parse/genparse) + +;; Note: By convention, nonterminals are prefixed with '@' and +;; terminals do not have a prefix. + +(define minijava-grammar-rules + '((@goal @program) + (:rule (lambda (x) x)) + (:java-rule ((program Program)) + Program + "program") + + ;; @program + + (@program @main-class) + (:rule (lambda (x) (ast-node program (:main-class x) (:class-list (list x))))) + (:java-rule ((mainClass MainClass)) + Program + "new Program(new ClassList(mainClass))") + + (@program @main-class @class-list) + (:rule (lambda (x y) (ast-node program (:main-class x) (:class-list (cons x y))))) + (:java-rule ((mainClass MainClas) (classList ClassList)) + Program + "new Program(new ClassList(mainClass).append(classList))") + + ;; @class-list + + (@class-list @class) + (:rule (lambda (x) (list x))) + (:java-rule ((_class _Class)) + ClassList + "new ClassList(_class)") + + (@class-list @class-list @class) + (:rule (lambda (x y) (append x (list y)))) + (:java-rule ((classList ClassList) (_class _Class)) + ClassList + "classList.append(_class)") + + ;; @main-class + + (@main-class class ident l-curl + public static void ident l-paren ident l-brak r-brak ident r-paren + l-curl @statement r-curl r-curl) + (:rule (lambda (class-1 ident-2 l-curl-3 public-4 static-5 void-6 ident-7 l-paren-8 ident-9 l-brak-10 r-brak-11 ident-12 r-paren-13 l-curl-14 @statement-15 r-curl-16 r-curl-17) + (ast-node class + (:class-name (token-value ident-2)) + (:line-col (token-line-col class-1)) + (:parent #f) + (:constructors '()) + (:potential-main-class #t) + (:instance-vars '()) ; var block + (:static-vars '()) + (:methods '()) + (:static-methods + (list (ast-node method + (:name (token-value ident-7)) + (:line-col (token-line-col public-4)) + (:return-type (ast-node simple-type (:name "void"))) + (:param-list '()) + (:static? #t) + (:param-list-main + (list (ast-node param + (:type (ast-node array-type + (:line-col (token-line-col ident-9)) + (:element-type (ast-node simple-type + (:line-col (token-line-col ident-9)) + (:name (token-value ident-9)))))) + (:line-col (token-line-col ident-9)) + (:name (token-value ident-12))))) + (:local-vars '()) + (:statements (list @statement-15)))))))) + (:java-rule ((classToken_1 Token) + (mainClassName_2 Token) + (leftCurl_3 Token) + (public_4 Token) + (static_5 Token) + (void_6 Token) + (mainMethodIdentifier_7 Token) + (leftParen_8 Token) + (paramTypeIdentifier_9 Token) + (leftBracket_10 Token) + (rightBracket_11 Token) + (paramIdentifier_12 Token) + (rightParen_13 Token) + (leftCurl_14 Token) + (statement_15 Statement) + (rightCurl_16 Token) + (rightCurl_17 Token)) + MainClass + "new MainClass(mainClassName_2, + mainMethodIdentifier_7, + paramTypeIdentifier_9, + paramIdentifier_12, + statement_15)") + + ;; @class + + (@class class ident @class-body) + (:rule (lambda (class ident @class-body) + (ast-node class + (:line-col (token-line-col class)) + (:class-name (token-value ident)) + (:parent #f) + (:instance-vars (list-ref @class-body 0)) + (:static-vars (list-ref @class-body 2)) + (:methods (list-ref @class-body 1)) + (:static-methods (list-ref @class-body 3)) + (:constructors (list-ref @class-body 4)) ))) + (:java-rule ((classToken Token) + (className Token) + (classBody ClassBody)) + _Class + "new _Class(className, null, classBody)") + + (@class class ident extends ident @class-body) + (:rule (lambda (class ident-name extends ident-parent @class-body) + (ast-node class + (:line-col (token-line-col class)) + (:class-name (token-value ident-name)) + (:parent (token-value ident-parent)) + (:instance-vars (list-ref @class-body 0)) + (:static-vars (list-ref @class-body 2)) + (:methods (list-ref @class-body 1)) + (:static-methods (list-ref @class-body 3)) + (:constructors (list-ref @class-body 4)) ))) + (:java-rule ((classToken Token) + (className Token) + (extendsToken Toke) + (parentName Token) + (classBody ClassBody)) + _Class + "new _Class(className, parentName, classBody)") + + ;; @class-body + + (@class-body l-curl @class-statement-block r-curl) + (:rule (lambda (x @class-statement-block y) + (let ((vars (filter-map (lambda (x) + (and (eqv? (car x) 'var) + (cdr x))) + @class-statement-block)) + (s-vars (filter-map (lambda (x) + (and (eqv? (car x) 'static-var) + (cdr x))) + @class-statement-block)) + (methods (filter-map (lambda (x) (and (eqv? (car x) 'method) + (not (@ast (cdr x) :static?)) + (cdr x))) + @class-statement-block)) + (s-methods (filter-map (lambda (x) (and (eqv? (car x) 'method) + (@ast (cdr x) :static?) + (cdr x))) + @class-statement-block)) + (ctors (filter-map (lambda (x) (and (eqv? 'ctor (car x)) + (cdr x))) + @class-statement-block))) + (list vars methods s-vars s-methods ctors)))) + (:java-rule ((leftCurl Token) + (classParts ClassParts) + (rightCurl Token)) + ClassBody + "new ClassBody(classParts)") + + (@class-body l-curl r-curl) + (:rule (lambda (x y) + (list '() + '() + '() ))) + (:java-rule ((leftCurl Token) + (rightCurl Token)) + ClassBody + "new ClassBody()") + + (@class-statement-block @class-statement) + (:rule (lambda (x) (list x))) + (:java-rule ((classPart ClassPart)) + ClassParts + "new ClassParts(classPart)") + + (@class-statement-block @class-statement-block @class-statement) + (:rule (lambda (x y) (append x (list y)))) + (:java-rule ((classParts ClassParts) + (classPart ClassPart)) + ClassParts + "classParts.append(classPart)") + + (@class-statement @var) + (:rule (lambda (@var) (cons 'var @var))) + (:java-rule ((v VariableDefinition)) + ClassPart + "new FieldDefinition(v)") + + (@class-statement @static-var) + (:rule (lambda (@static-var) (cons 'static-var @static-var))) + (:java-rule ((sv StaticVariableDefinition)) + ClassPart + "new StaticFieldDefinition(sv)") + + (@class-statement @method) + (:rule (lambda (@method) (cons 'method @method))) + (:java-rule ((method MethodDefition)) + ClassPart + "method") + + (@class-statement @constructor) + (:rule (lambda (@constructor) (cons 'ctor @constructor))) + (:java-rule ((constructor ConstructorDefinition)) + ClassPart + "constructor") + + ;; @var-block + + (@var-block @var) + (:rule (lambda (v) + (list v))) + (:java-rule ((v VariableDefinition)) + VariableBlock + "new VariableBlock(v)") + + (@var-block @var-block @var) + (:rule (lambda (@var-block @var) + (append @var-block (list @var)))) + (:java-rule ((vb VariableBlock) + (v VariableDefinition)) + VariableBlock + "VariableBlock.append(vb, v)") + + ;; @var + + (@var @type ident s-colon) + (:rule (lambda (@type ident s-colon) + (ast-node var + (:line-col (@ast @type :line-col)) + (:name (token-value ident)) + (:type @type)))) + (:java-rule ((type TypeSpecifier) + (identifier Token) + (semicolon Token)) + VariableDefinition + "new VariableDefinition(type, identifier)") + + ;; @static-var + + (@static-var static @type ident s-colon) + (:rule (lambda (x @type ident s-colon) + (ast-node static-var + (:line-col (token-line-col x)) + (:name (token-value ident)) + (:type @type)))) + (:java-rule ((staticToken Token) + (type TypeSpecifier) + (identifier Token) + (semicolon Token)) + VariableDefintion + "new VariableDefinition(type, identifier)") + + ;; @constructor + + (@constructor public ident l-paren r-paren @method-body) + (:rule (lambda (x ident y z @method-body) + (ast-node constructor + (:line-col (list-ref x 2)) + (:param-list '()) + (:static? #t) + (:return-type (ast-node user-type (:name (token-value ident)))) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1)) ) )) + (:java-rule ((publicToken Token) + (identifier Token) + (leftParen Token) + (rightParen Token) + (body MethodBody)) + ConstructorDefinition + "new ConstructorDefinition(identifier, + new ParameterList(), + body)") + + (@constructor public ident l-paren @param-list r-paren @method-body) + (:rule (lambda (--x ident --y @param-list --z @method-body) + (ast-node constructor + (:line-col (list-ref --x 2)) + (:param-list @param-list) + (:static? #t) + (:return-type (ast-node user-type (:name (token-value ident)))) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1)) ) )) + (:java-rule ((publicToken Token) + (identifier Token) + (leftParen Token) + (parameterList ParameterList) + (rightParen Token) + (body MethodBody)) + ConstructorDefinition + "new ConstructorDefinition(identifier, + parameterList, + body)") + + ;; @method + + (@method @method-start r-paren @method-body) + (:rule (lambda (@method-start r-paren @method-body) + (ast-node method + (:line-col (list-ref @method-start 2)) + (:name (list-ref @method-start 1)) + (:param-list '()) + (:return-type (list-ref @method-start 0)) + (:static? (list-ref @method-start 3)) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1))))) + (:java-rule ((attributes MethodAttributes) + (rightParen Token) + (body MethodBody)) + MethodDefinition + "new MethodDefinition(attributes, new ParameterList(), body)") + + (@method @method-start @param-list r-paren @method-body) + (:rule (lambda (@method-start @param-list r-paren @method-body) + (ast-node method + (:line-col (list-ref @method-start 2)) + (:name (list-ref @method-start 1)) + (:param-list @param-list) + (:return-type (list-ref @method-start 0)) + (:static? (list-ref @method-start 3)) + (:local-vars (list-ref @method-body 0)) + (:statements (list-ref @method-body 1))))) + (:java-rule ((attributes MethodAttributes) + (parameters ParameterList) + (rightParen Token) + (body MethodBody)) + MethodDefinition + "new MethodDefinition(attributes, parameters, body)") + +;; (@method --sasm-impl public static @type @method-ident l-paren @param-list r-paren s-colon) +;; (:rule (lambda (--sasm-impl --public --static @type @method-ident --l-paren @param-list --r-paren --s-colon) +;; (ast-node method +;; (:sasm-impl-no-codegen #t) +;; (:line-col (token-line-col --sasm-impl)) +;; (:name (token-value @method-ident)) +;; (:param-list @param-list) +;; (:return-type @type) +;; (:static? #t) +;; (:local-vars '()) +;; (:statements '())))) + + (@method --sasm-impl public static @type @method-ident l-paren @param-list r-paren = ident s-colon) + (:rule (lambda (--sasm-impl --public --static @type method-name@method-ident --l-paren @param-list --r-paren --= sasm-ident@method-ident --s-colon) + (ast-node method + (:sasm-impl-no-codegen #t) + (:static-method-alternate-identifier (token-value sasm-ident@method-ident)) + (:line-col (token-line-col --sasm-impl)) + (:name (token-value method-name@method-ident)) + (:param-list @param-list) + (:return-type @type) + (:static? #t) + (:local-vars '()) + (:statements '())))) + (:java-rule ((sasmImplToken Token) + (publicToken Token) + (staticToken Token) + (returnType TypeSpecifier) + (methodIdentifier Token) + (leftParen Token) + (parameters ParameterList) + (rightParen Token) + (equals Token) + (sasmIdentifier Token) + (semicolon Token)) + MethodDefinition + "new NativeMethodDefinition(returnType, methodIdentifier, parameters, sasmIdentifier)") + + (@method --sasm-impl public static @type @method-ident l-paren r-paren = ident s-colon) + (:rule (lambda (--sasm-impl --public --static @type method-name@method-ident --l-paren --r-paren --= sasm-ident@method-ident --s-colon) + (ast-node method + (:sasm-impl-no-codegen #t) + (:static-method-alternate-identifier (token-value sasm-ident@method-ident)) + (:line-col (token-line-col --sasm-impl)) + (:name (token-value method-name@method-ident)) + (:param-list '()) + (:return-type @type) + (:static? #t) + (:local-vars '()) + (:statements '())))) + (:java-rule ((sasmImplToken Token) + (publicToken Token) + (staticToken Token) + (returnType TypeSpecifier) + (methodIdentifier Token) + (leftParen Token) + (rightParen Token) + (equals Token) + (sasmIdentifier Token) + (semicolon Token)) + MethodDefinition + "new NativeMethodDefinition(returnType, methodIdentifier, new ParameterList(), sasmIdentifier)") + + ;; @method-start + + (@method-start public @type @method-ident l-paren) + (:rule (lambda (x @type ident y) + (list @type (token-value ident) (token-line-col x) #f))) + (:java-rule ((publicToken Token) + (returnType TypeSpecifier) + (name Token) + (leftParen Token)) + MethodAttributes + "new MethodAttributes(returnType, name)") + + (@method-start public static @type @method-ident l-paren) + (:rule (lambda (x y @type ident z) + (list @type (token-value ident) (token-line-col x) #t))) + (:java-rule ((publicToken Token) + (staticToken Token) + (returnType TypeSpecifier) + (name Token) + (leftParen Token)) + MethodAttributes + "new StaticMethodAttributes(returnType, name)") + + (@method-ident ident) + (:rule (lambda (x) x)) + (:java-rule ((identifier Token)) + Token + "identifier") + + (@method-ident length) + (:rule (lambda (x) x)) + (:java-rule ((identifier Token)) + Token + "identifier") + + ;; @param-list + + (@param-list @param) + (:rule (lambda (x) (list x))) + (:java-rule ((parameter Parameter)) + ParameterList + "new ParameterList(parameter)") + + (@param-list @param-list comma @param) + (:rule (lambda (a comma b) (append a (list b)))) + (:java-rule ((parameterList ParameterList) + (comma Token) + (parameter Parameter)) + ParameterList + "parameterList.append(parameter)") + + ;; @param + + (@param @type ident) + (:rule (lambda (@type ident) + (ast-node param + (:line-col (@ast @type :line-col)) + (:type @type) + (:name (token-value ident))))) + (:java-rule ((type TypeSpecifier) + (identifier Token)) + Parameter + "new Parameter(type, identifier)") + + ;; @method-body + + (@method-body l-curl @var-block @statement-block r-curl) + (:rule (lambda (l-curl @var-block @statement-block r-curl) + (list @var-block + @statement-block))) + (:java-rule ((leftCurly Token) + (variables VariableBlock) + (statements StatementBlock) + (rightCurly Token)) + MethodBody + "new MethodBody(variables, statements)") + + (@method-body l-curl @statement-block r-curl) + (:rule (lambda (l-curl @statement-block r-curl) + (list '() + @statement-block))) + (:java-rule ((leftCurly Token) + (statements StatementBlock) + (rightCurly Token)) + MethodBody + "new MethodBody(new VariableBlock(), statements)") + + (@method-body l-curl r-curl) + (:rule (lambda (l-curl r-curl) + (list '() '()))) + (:java-rule ((leftCurly Token) + (rightCurly Token)) + MethodBody + "new MethodBody(new VariableBlock(), new StatementBlock())") + + ;; @statement-block + + (@statement-block @statement) + (:rule (lambda (x) (list x))) + (:java-rule ((statement Statement)) + StatementBlock + "new StatementBlock(statement)") + + (@statement-block @statement-block @statement) + (:rule (lambda (x y) (append x (list y)))) + (:java-rule ((statementBlock StatementBlock) + (statement Statement)) + "statementBlock.append(statement)") + + ;; @type + + (@type int l-brak r-brak) + (:rule (lambda (x y z) + (ast-node array-type + (:line-col (token-line-col x)) + (:element-type (ast-node simple-type + (:name "int")))))) + (:java-rule ((name Token) + (leftBracket Token) + (rightBracket Token)) + TypeSpecifier + "new ArrayTypeSpecifier(new SimpleTypeSpecifier(name))") + + (@type char l-brak r-brak) + (:rule (lambda (x y z) + (ast-node array-type + (:line-col (token-line-col x)) + (:element-type (ast-node simple-type + (:name "char")))))) + (:java-rule ((name Token) + (leftBracket Token) + (rightBracket Token)) + TypeSpecifier + "new ArrayTypeSpecifier(new SimpleTypeSpecifier(name))") + + + (@type ident l-brak r-brak) + (:rule (lambda (ident y z) + (ast-node array-type + (:line-col (token-line-col ident)) + (:element-type (ast-node user-type + (:name (token-value ident))))))) + (:java-rule ((name Token) + (leftBracket Token) + (rightBracket Token)) + TypeSpecifier + "new ArrayTypeSpecifier(new SimpleTypeSpecifier(name))") + + + (@type boolean) + (:rule (lambda (x) + (ast-node simple-type + (:line-col (token-line-col x)) + (:name "boolean")))) + (:java-rule ((name Token)) + TypeSpecifier + "new SimpleTypeSpecifier(name)") + + (@type int) + (:rule (lambda (x) + (ast-node simple-type + (:line-col (token-line-col x)) + (:name "int")))) + (:java-rule ((name Token)) + TypeSpecifier + "new SimpleTypeSpecifier(name)") + + (@type char) + (:rule (lambda (x) + (ast-node simple-type + (:line-col (token-line-col x)) + (:name "char")))) + (:java-rule ((name Token)) + TypeSpecifier + "new SimpleTypeSpecifier(name)") + + (@type ident) + (:rule (lambda (ident) + (ast-node user-type + (:line-col (token-line-col ident)) + (:name (token-value ident))))) + (:java-rule ((name Token)) + TypeSpecifier + "new SimpleTypeSpecifier(name)") + + ;; @statement + + (@statement l-curl r-curl) + (:rule (lambda (x y) + (ast-node compound-statement + (:line-col (token-line-col x)) + (:statements '())))) + (:java-rule ((leftCurly Token) + (rightCurly Token)) + Statement + "new CompoundStatement()") + + (@statement l-curl @statement-block r-curl) + (:rule (lambda (x @statement-block z) + (ast-node compound-statement + (:line-col (token-line-col x)) + (:statements @statement-block)))) + (:java-rule ((leftCurly Token) + (block StatementBlock) + (rightCurly Token)) + Statement + "new CompoundStatement(block)") + + (@statement if l-paren @exp r-paren @statement else @statement) + (:rule (lambda (if-tok l-paren @exp r-paren @statement-consequent else @statement-antecedent) + (ast-node if-statement + (:line-col (token-line-col if-tok)) + (:condition @exp) + (:consequent @statement-consequent) + (:antecedent @statement-antecedent)))) + (:java-rule ((ifToken Token) + (leftParen Token) + (predicate Expression) + (rightParen Token) + (consequent Statement) + (elseToken Token) + (antecedent Statement)) + Statement + "new ConditionalStatement(predicate, consequent, antecedent)") + + (@statement while l-paren @exp r-paren @statement) + (:rule (lambda (while l-paren @exp r-paren @statement) + (ast-node while-statement + (:line-col (token-line-col while)) + (:condition @exp) + (:body @statement)))) + (:java-rule ((whileToken Token) + (leftParen Token) + (predicate Expression) + (rightParen Token) + (body Statement)) + Statement + "new WhileLoopStatement(predicate, body)") + + + (@statement system-out-println l-paren @exp r-paren s-colon) + (:rule (lambda (x y @exp z w) + (ast-node print-statement + (:line-col (token-line-col x)) + (:exp @exp)))) + (:java-rule ((sopToken Token) + (leftParen Token) + (argument Expression) + (rightParen Token) + (semicolon Token)) + Statement + "new PrintStatement(argument)") + + (@statement ident = @exp s-colon) + (:rule (lambda (ident x @exp y) + (ast-node assignment-statement + (:line-col (token-line-col ident)) + (:ident (token-value ident)) + (:exp @exp)))) + (:java-rule ((identifier Token) + (equals Token) + (value Expression) + (semicolon Token)) + Statement + "new AssignmentStatement(identifier, value)") + + (@statement ident l-brak @exp r-brak = @exp s-colon) + (:rule (lambda (ident x @index-exp y z @value-exp w) + (ast-node array-assignment-statement + (:line-col (token-line-col ident)) + (:ident (token-value ident)) + (:index-exp @index-exp) + (:value-exp @value-exp)))) + (:java-rule ((identifier Token) + (leftBracket Token) + (indexExpression Expression) + (rightBracket Token) + (equals Token) + (value Expression) + (semicolon Token)) + Statement + "new ArrayAssignmentStatement(identifier, indexExpression, value)") + + (@statement return @exp s-colon) + (:rule (lambda (r @exp s) + (ast-node return-statement + (:line-col (token-line-col r)) + (:exp @exp)))) + (:java-rule ((returnToken Token) + (value Expression) + (semicolon Token)) + Statement + "new ReturnValueStatement(value)") + + (@statement return s-colon) + (:rule (lambda (r s) + (ast-node return-statement + (:line-col (token-line-col r))))) + (:java-rule ((returnToken Token) + (semicolon Token)) + Statement + "new EmptyReturnStatement()") + + ;; @exp + + (@exp @exp-logical) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + ;; @exp-logical + + (@exp-logical @exp-comparison) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + (@exp-logical @exp-logical && @exp-comparison) + (:rule (lambda (@exp-logical foo @exp-comparison) + (ast-node and-expression + (:line-col (token-line-col foo)) + (:left @exp-logical) + (:right @exp-comparison)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new LogicalAndExpression(lhs, rhs)") + + ;; @exp-comparison + + (@exp-comparison @exp-term) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + (@exp-comparison @exp-term < @exp-term) + (:rule (lambda (@exp-term-left foo @exp-term-right) + (ast-node less-than-expression + (:line-col (token-line-col foo)) + (:left @exp-term-left) + (:right @exp-term-right)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new LessThanExpression(lhs, rhs)") + + (@exp-comparison @exp-term == @exp-term) + (:rule (lambda (@exp-term-left foo @exp-term-right) + (ast-node equal-to-expression + (:line-col (token-line-col foo)) + (:left @exp-term-left) + (:right @exp-term-right)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new EqualityExpression(lhs, rhs)") + + ;; @exp-term + + (@exp-term @exp-factor) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + (@exp-term @exp-term + @exp-factor) + (:rule (lambda (@exp-term foo @exp-factor) + (ast-node add-expression + (:line-col (token-line-col foo)) + (:left @exp-term) + (:right @exp-factor)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new AdditionExpression(lhs, rhs)") + + (@exp-term @exp-term - @exp-factor) + (:rule (lambda (@exp-term foo @exp-factor) + (ast-node subtract-expression + (:line-col (token-line-col foo)) + (:left @exp-term) + (:right @exp-factor)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new SubtractionExpression(lhs, rhs)") + + (@exp-factor @exp-factor pipe @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-or) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new BinaryOrExpression(lhs, rhs)") + + (@exp-factor @exp-factor & @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-and) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new BinaryAndExpression(lhs, rhs)") + + (@exp-factor @exp-factor ^ @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-xor) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new BinaryExclusiveOrExpression(lhs, rhs)") + + ;; @exp-factor + + (@exp-factor @exp-elem) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + (@exp-factor @exp-factor * @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node multiply-expression + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new MultiplicationExpression(lhs, rhs)") + + (@exp-factor @exp-factor >> @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-arith-rshift) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new ShiftRightExpression(lhs, rhs)") + + (@exp-factor @exp-factor << @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-lshift) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new ShiftLeftExpression(lhs, rhs)") + + (@exp-factor @exp-factor >>> @exp-elem) + (:rule (lambda (@exp-factor foo @exp-elem) + (ast-node int-binop-expression + (:op 'bit-rshift) + (:line-col (token-line-col foo)) + (:left @exp-factor) + (:right @exp-elem)))) + (:java-rule ((lhs Expression) + (operator Token) + (rhs Expression)) + Expression + "new ArithmeticShiftRightExpression(lhs, rhs)") + + ;; @exp-elem + + (@exp-elem @exp-array) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + (@exp-elem @exp-ref) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + (@exp-elem bang @exp-elem) + (:rule (lambda (foo @exp-elem) + (ast-node not-expression + (:line-col (token-line-col foo)) + (:exp @exp-elem)))) + (:java-rule ((notOperator Token) + (expression Expression)) + Expression + "new LogicalNotExpression(expression)") + + (@exp-elem ~ @exp-elem) + (:rule (lambda (foo @exp-elem) + (ast-node int-unop-expression + (:op 'bit-not) + (:line-col (token-line-col foo)) + (:exp @exp-elem)))) + (:java-rule ((notOperator Token) + (expression Expression)) + Expression + "new BinaryNotExpression(expression)") + + ;; @exp-array + + (@exp-array @exp-ref l-brak @exp r-brak) + (:rule (lambda (@exp-ref foo-1 @exp foo-2) + (ast-node array-ref-expression + (:line-col (@ast @exp-ref :line-col)) + (:array-exp @exp-ref) + (:index-exp @exp)))) + (:java-rule ((arrayExpression Expression) + (leftBracket Token) + (indexExpression Expression) + (rightBracket Token)) + Expression + "new ArrayReferenceExpression(arrayExpression, indexExpression)") + + ;; @exp-ref + + (@exp-ref @exp-ref dot length) + (:rule (lambda (@exp-ref foo-1 foo-2) + (ast-node length-expression + (:line-col (@ast @exp-ref :line-col)) + (:exp @exp-ref)))) + (:java-rule ((arrayExpression Expression) + (dot Token) + (length Token)) + Expression + "new ArrayLengthExpression(arrayExpression)") + + (@exp-ref @exp-ref dot @method-ident l-paren r-paren) + (:rule (lambda (@exp-ref foo-1 ident foo-2 foo-3) + (ast-node method-call-expression + (:line-col (@ast @exp-ref :line-col)) + (:object @exp-ref) + (:method-name (token-value ident)) + (:arg-list '())))) + (:java-rule ((objectExpression Expression) + (dot Token) + (methodName Token) + (leftParen Token) + (rightParen Token)) + Expression + "new MethodCallExpression(objectExpression, methodName, new ExpressionList())") + + (@exp-ref @exp-ref dot @method-ident l-paren @exp-list r-paren) + (:rule (lambda (@exp-ref foo-1 ident foo-2 @exp-list foo-3) + (ast-node method-call-expression + (:line-col (@ast @exp-ref :line-col)) + (:object @exp-ref) + (:method-name (token-value ident)) + (:arg-list @exp-list)))) + (:java-rule ((objectExpression Expression) + (dot Token) + (methodName Token) + (leftParen Token) + (arguments ExpressionList) + (rightParen Token)) + Expression + "new MethodCallExpression(objectExpression, methodName, arguments)") + + (@exp-ref @exp-trivial) + (:rule (lambda (x) x)) + (:java-rule ((expression Expression)) + Expression + "expression") + + ;; @exp-trivial + + (@exp-trivial number) + (:rule (lambda (x) + (ast-node number-constant-expression + (:line-col (token-line-col x)) + (:value (token-value x))))) + (:java-rule ((number Token)) + Expression + "new NumericLiteralExpression(number)") + + (@exp-trivial true) + (:rule (lambda (x) + (ast-node boolean-constant-expression + (:line-col (token-line-col x)) + (:value "true") + (:scheme-value #t)))) + (:java-rule ((trueToken Token)) + Expression + "new BooleanLiteralExpression(true)") + + (@exp-trivial false) + (:rule (lambda (y) + (ast-node boolean-constant-expression + (:line-col (token-line-col y)) + (:value "false") + (:scheme-value #f)))) + (:java-rule ((falseToken Token)) + Expression + "new BooleanLiteralExpression(false)") + + (@exp-trivial char-literal) + (:rule (lambda (c) + (ast-node char-constant-expression + (:line-col (token-line-col c)) + (:value (token-value c))))) + (:java-rule ((character Token)) + Expression + "new CharacterLiteralExpresion(character)") + + (@exp-trivial string-literal) + (:rule (lambda (s) + (ast-node new-object-expression + (:line-col (token-line-col s)) + (:class-name "String") + (:arg-list (list + (ast-node string-constant-expression + (:line-col (token-line-col s)) + (:value (token-value s)))))))) + (:java-rule ((string Token)) + Expression + "new StringLiteralExpresion(string)") + + (@exp-trivial ident) + (:rule (lambda (y) + (ast-node variable-expression + (:line-col (token-line-col y)) + (:ident (token-value y))))) + (:java-rule ((identifier Token)) + Expression + "new VariableReferenceExpresion(ident)") + + (@exp-trivial this) + (:rule (lambda (y) + (ast-node this-expression + (:line-col (token-line-col y))))) + (:java-rule ((thisToken Token)) + Expression + "new ThisReferenceExpresion()") + + (@exp-trivial new int l-brak @exp r-brak) + (:rule (lambda (foo-1 foo-2 foo-3 @exp foo-4) + (ast-node new-array-expression + (:line-col (token-line-col foo-1)) + (:element-type (ast-node simple-type + (:name "int"))) + (:length @exp)))) + (:java-rule ((newToken Token) + (type Token) + (leftBracket Token) + (sizeExpression Expression) + (rightBracket Token)) + Expression + "new NewArrayExpression(type, sizeExpression)") + + (@exp-trivial new char l-brak @exp r-brak) + (:rule (lambda (foo-1 foo-2 foo-3 @exp foo-4) + (ast-node new-array-expression + (:line-col (token-line-col foo-1)) + (:element-type (ast-node simple-type + (:name "char"))) + (:length @exp)))) + (:java-rule ((newToken Token) + (type Token) + (leftBracket Token) + (sizeExpression Expression) + (rightBracket Token)) + Expression + "new NewArrayExpression(type, sizeExpression)") + + (@exp-trivial new ident l-brak @exp r-brak) + (:rule (lambda (foo-1 @ident foo-3 @exp foo-4) + (ast-node new-array-expression + (:line-col (token-line-col foo-1)) + (:element-type (ast-node user-type + (:name (token-value @ident)))) + (:length @exp)))) + (:java-rule ((newToken Token) + (typeName Token) + (leftBracket Token) + (sizeExpression Expression) + (rightBracket Token)) + Expression + "new NewArrayExpression(typeName, sizeExpression)") + + (@exp-trivial new ident l-paren r-paren) + (:rule (lambda (foo-1 ident foo-2 foo-3) + (ast-node new-object-expression + (:line-col (token-line-col foo-1)) + (:class-name (token-value ident)) + (:arg-list '())))) + (:java-rule ((newToken Token) + (typeName Token) + (leftParen Token) + (rightParen Token)) + Expression + "new NewObjectExpression(typeName, new ExpressionList())") + + (@exp-trivial new ident l-paren @exp-list r-paren) + (:rule (lambda (foo:new ident foo:l-paren @exp-list foo:r-paren) + (ast-node new-object-expression + (:line-col (token-line-col foo:new)) + (:class-name (token-value ident)) + (:arg-list @exp-list)))) + (:java-rule ((newToken Token) + (typeName Token) + (leftParen Token) + (arguments ExpressionList) + (rightParen Token)) + Expression + "new NewObjectExpression(typeName, arguments)") + + (@exp-trivial l-paren @exp r-paren) + (:rule (lambda (foo-1 @exp foo-2) + @exp)) + (:java-rule ((leftParen Token) + (expression Expression) + (rightParen Token)) + Expression + "expression") + + ;; @exp-list + + (@exp-list @exp) + (:rule (lambda (x) (list x))) + (:java-rule ((expression Expression)) + ExpressionList + "new ExpressionList(expression)") + + + (@exp-list @exp-list comma @exp) + (:rule (lambda (x y z) (append x (list z)))) + (:java-rule ((expressionList ExpressionList) + (comma Token) + (expression Expression)) + ExpressionList + "ExpressionList.append(expressionList, expression)") + + )) + +(define minijava-grammar + (grammar-rules-filter-productions minijava-grammar-rules)) + +(define minijava-graph (build-lr0-state-transition-graph minijava-grammar)) +(define minijava-sr-table (generate-lr0-table minijava-grammar minijava-graph minijava-grammar-rules)) +(define minijava-goto-table (generate-lr0-goto-table minijava-grammar minijava-graph)) +(define minijava-terminals (grammar-terminals minijava-grammar)) +(define minijava-nonterminals (grammar-nonterminals minijava-grammar)) +(define minijava-action-table (grammar-rules-build-action-table minijava-grammar-rules)) + +(if (file-exists? "minijava-parser.scm") + (delete-file "minijava-parser.scm")) + +(call-with-output-file "minijava-parser.scm" + (lambda (port) + (for-each + (lambda (code) (write code port) (newline port)) + `((need parse/parse) + (need ast) + (define action-table ,minijava-action-table) + (define (minijava-parse-input input) + (run-parse (quote ,minijava-grammar) + (quote ,(append minijava-terminals (list '$))) + (quote ,minijava-nonterminals) + (quote ,minijava-sr-table) + (quote ,minijava-goto-table) + action-table + input)) + (define (minijava-parse-port input-port) + (minijava-parse-input (read input-port))) + (define (minijava-parse-file filename) + (call-with-input-file filename + minijava-parse-port)))))) diff --git a/src/minijava-lexer-java.scm b/src/minijava-lexer-java.scm new file mode 100644 index 0000000..6b6179a --- /dev/null +++ b/src/minijava-lexer-java.scm @@ -0,0 +1,4 @@ +(need regex/dfa) +(need regex/genlex) +(define minijava-lexer-dfa (build-fast-dfa (quote 282) (quote #(#t #t #t #t #t #t #t #t #t #t #t #f #f #f #f #f #f #t #t #t #t #t #f #f #f #t #t #f #f #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #t #t #t #t #f #f #f #f #t #t #f #t #t #t)) (quote #(#(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 0 0 0 0 0 0 0 0 0 0 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 1 #f #f #f #f #f #f #f #f 5 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 3 #f #f #f #f #f #f #f #f 7 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 0 0 0 0 0 0 0 0 0 0 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 1 #f #f #f #f #f #f #f #f 5 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 3 #f #f #f #f #f #f #f #f 7 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 11 11 20 11 #f 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 16 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 11 11 20 11 #f 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 16 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 11 11 20 11 #f 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 16 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 11 11 20 11 #f 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 16 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f 13 #f 13 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 13 #f #f #f 13 #f 13 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 11 11 20 11 #f 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 16 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 25 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f 23 #f 23 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 25 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 27 27 27 27 #f 27 27 #f 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 24 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 33 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 34 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 35 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 36 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 38 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 39 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 41 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 42 212 212 212 212 212 212 212 212 40 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 44 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 45 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 43 212 212 212 212 212 212 212 212 212 46 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 56 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 57 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 59 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 61 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 63 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 65 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 66 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 67 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 68 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 70 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 71 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 72 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 73 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 74 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 76 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 77 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 78 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 79 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 80 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 81 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 84 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 83 212 212 212 212 212 212 212 85 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 90 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 91 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 92 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 94 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 95 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 96 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 97 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 98 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 104 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 105 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 107 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 108 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 106 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 110 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 111 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 113 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 114 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 115 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 116 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 117 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 112 212 212 212 212 212 212 212 212 212 212 212 118 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 120 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 121 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 122 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 123 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 124 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 126 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 127 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 128 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 129 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 131 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 132 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 133 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 130 134 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 136 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 137 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 139 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 140 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 141 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 138 212 212 212 142 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 243 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 244 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 245 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 246 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 247 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 248 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 249 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 250 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 212 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 251 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f #f #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f 252 #f 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 256 256 #f #f 256 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 256 256 256 256 #f 256 256 256 256 256 274 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 256 256 #f #f 256 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 256 256 256 256 #f 256 256 256 256 256 274 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 256 256 #f #f 256 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 256 256 256 256 #f 256 256 256 256 256 274 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 256 256 #f #f 256 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 256 256 256 256 #f 256 256 256 256 256 274 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 256 256 #f #f 256 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 256 256 256 256 #f 256 256 256 256 256 274 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 260 260 #f #f 260 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 260 260 260 260 #f 260 260 260 260 260 274 260 260 260 260 256 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 260 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 265 265 #f #f 265 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 265 265 265 265 #f 265 265 265 265 265 267 265 265 265 265 269 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 265 265 #f #f 265 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 265 265 265 265 #f 265 265 265 265 265 267 265 265 265 265 269 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 265 265 #f #f 265 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 265 265 265 265 #f 265 265 265 265 265 267 265 265 265 265 269 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 265 265 #f #f 265 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 265 265 265 265 #f 265 265 265 265 265 267 265 265 265 265 269 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 265 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 256 256 #f #f 256 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 256 256 256 256 #f 256 256 256 256 256 274 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 276 278 #f #f 276 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 276 276 276 276 #f 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 #f 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 276 278 #f #f 276 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 276 276 276 276 #f 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 #f 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 276 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 275 #f #f #f #f 279 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 281 281 #f #f 281 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 281 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 281 281 #f #f 281 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 281 32 22 #f #f 29 62 28 103 102 53 55 31 54 52 280 9 9 9 9 9 9 9 9 9 9 30 87 60 64 58 51 #f 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 89 #f 88 48 253 #f 10 82 143 10 119 37 10 10 86 10 10 125 10 109 10 99 10 75 135 47 10 93 69 10 10 10 101 50 100 49 #f) #() #()))) (quote #(number number number number number number number number number number ident #f #f #f #f #f #f string-literal string-literal string-literal string-literal string-literal #f #f #f char-literal char-literal #f #f percent colon comma bang false ident ident ident ident throw ident ident this ident ident true ident ident ident ^ ~ pipe ? dot * - + >>> >> > << < && & == = while ident ident ident ident return ident ident ident ident ident boolean ident ident ident ident ident ident if int ident ident s-colon r-brak l-brak void ident ident ident public ident ident ident ident ident r-curl l-curl r-paren l-paren null ident ident new ident ident else ident ident extends ident ident ident ident ident ident length ident ident ident ident ident static ident ident ident ident super ident ident ident ident char ident ident class ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident --sasm-impl ident ident ident ident ident ident ident ident ident ident #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f *comment* *comment* *comment* *comment* #f #f #f #f *comment* *comment* #f forward-slash *whitespace* *whitespace*)))) +(define minijava-lexically-analyze (let ((main-dfa minijava-lexer-dfa)) (lambda (input-port) (run-generated-lexer main-dfa (quote (*whitespace* *comment*)) input-port)))) diff --git a/src/minijava-lexer.scm b/src/minijava-lexer.scm new file mode 100644 index 0000000..639c3ad --- /dev/null +++ b/src/minijava-lexer.scm @@ -0,0 +1,4 @@ +(need regex/dfa) +(need regex/genlex) +(define minijava-lexer-dfa (build-fast-dfa (quote 296) (quote #(#t #t #t #t #t #t #t #t #t #t #t #f #f #f #f #f #f #t #t #t #t #t #f #f #f #t #t #f #f #t #t #t #f #f #f #f #f #f #f #f #f #f #f #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #t #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #t #t #t #t #f #f #f #f #t #t #f #f #t #t)) (quote #(#(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 0 0 0 0 0 0 0 0 0 0 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 1 #f #f #f #f #f #f #f #f 5 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 3 #f #f #f #f #f #f #f #f 8 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 0 0 0 0 0 0 0 0 0 0 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 1 #f #f #f #f #f #f #f #f 5 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 3 #f #f #f #f #f #f #f #f 8 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 17 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 17 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 17 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 17 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f 14 #f 14 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 14 #f #f #f 14 #f 14 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 12 12 17 12 #f 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 15 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 26 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 23 #f #f #f 23 #f 23 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 26 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 27 27 27 27 #f 27 27 #f 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 24 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 31 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 32 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 33 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 34 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 35 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 36 #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 37 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 38 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 39 #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 40 #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 41 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 42 #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 43 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 44 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 45 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 46 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 47 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 49 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 51 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 52 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 50 222 222 53 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 54 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 56 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 57 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 59 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 60 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 58 222 222 222 222 222 222 222 222 222 61 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 71 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 72 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 74 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 76 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 78 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 80 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 81 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 82 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 83 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 85 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 86 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 87 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 88 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 89 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 91 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 92 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 93 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 94 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 95 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 96 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 99 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 98 222 222 222 222 222 222 222 100 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 105 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 106 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 107 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 109 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 110 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 111 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 112 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 113 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 119 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 120 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 122 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 123 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 125 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 126 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 127 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 128 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 129 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 124 222 222 222 222 222 222 222 222 222 222 222 130 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 132 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 133 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 134 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 135 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 136 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 138 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 139 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 140 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 141 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 143 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 144 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 145 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 142 146 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 148 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 149 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 151 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 152 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 153 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 150 222 222 222 154 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 257 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 258 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 259 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 260 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 261 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 262 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 263 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 264 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 222 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 265 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f #f #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f 266 #f 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 268 268 #f #f 268 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 268 268 268 268 #f 268 268 268 268 268 287 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 268 268 #f #f 268 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 268 268 268 268 #f 268 268 268 268 268 287 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 268 268 #f #f 268 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 268 268 268 268 #f 268 268 268 268 268 287 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 268 268 #f #f 268 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 268 268 268 268 #f 268 268 268 268 268 287 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 268 268 #f #f 268 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 268 268 268 268 #f 268 268 268 268 268 287 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 273 273 #f #f 273 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 273 273 273 273 #f 273 273 273 273 273 287 273 273 273 273 268 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 273 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 278 278 #f #f 278 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 278 278 278 278 #f 278 278 278 278 278 282 278 278 278 278 284 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 278 278 #f #f 278 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 278 278 278 278 #f 278 278 278 278 278 282 278 278 278 278 284 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 278 278 #f #f 278 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 278 278 278 278 #f 278 278 278 278 278 282 278 278 278 278 284 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 278 278 #f #f 278 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 278 278 278 278 #f 278 278 278 278 278 282 278 278 278 278 284 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 278 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 268 268 #f #f 268 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 268 268 268 268 #f 268 268 268 268 268 287 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 268 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 290 292 #f #f 290 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 290 290 290 290 #f 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 #f 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 290 292 #f #f 290 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 290 290 290 290 #f 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 #f 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 290 #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 289 #f #f #f #f 293 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 295 295 #f #f 295 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 295 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #() #()) #(#(#f #f #f #f #f #f #f #f #f 295 295 #f #f 295 #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f 295 30 22 #f #f #f 77 28 118 117 68 70 29 69 67 294 9 9 9 9 9 9 9 9 9 9 #f 102 75 79 73 66 #f 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 48 10 10 10 10 10 10 10 104 #f 103 63 267 #f 10 97 155 10 131 55 10 10 101 10 10 137 10 121 10 114 10 90 147 62 10 108 84 10 10 10 116 65 115 64 #f) #() #()))) (quote #(number number number number number number number number number number ident #f #f #f #f #f #f string-literal string-literal string-literal string-literal string-literal #f #f #f char-literal char-literal #f #f comma bang system-out-println #f #f #f #f #f #f #f #f #f #f #f ident ident ident ident ident ident fail ident false ident ident ident ident this ident ident true ident ident ident ^ ~ pipe ? dot * - + >>> >> > << < && & == = while ident ident ident ident return ident ident ident ident ident boolean ident ident ident ident ident ident if int ident ident s-colon r-brak l-brak void ident ident ident public ident ident ident ident ident r-curl l-curl r-paren l-paren new ident ident else ident ident extends ident ident ident ident ident ident length ident ident ident ident ident static ident ident ident ident super ident ident ident ident char ident ident class ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident ident --sasm-impl ident ident ident ident ident ident ident ident ident ident #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f *comment* *comment* *comment* *comment* #f #f #f #f *comment* *comment* #f #f *whitespace* *whitespace*)))) +(define minijava-lexically-analyze (let ((main-dfa minijava-lexer-dfa)) (lambda (input-port) (run-generated-lexer main-dfa (quote (*whitespace* *comment*)) input-port)))) diff --git a/src/minijava-parser.scm b/src/minijava-parser.scm new file mode 100644 index 0000000..b57da84 --- /dev/null +++ b/src/minijava-parser.scm @@ -0,0 +1,6 @@ +(need parse/parse) +(need ast) +(define action-table (vector (lambda (x) x) (lambda (x) (ast-node program (:main-class x) (:class-list (list x)))) (lambda (x y) (ast-node program (:main-class x) (:class-list (cons x y)))) (lambda (x) (list x)) (lambda (x y) (append x (list y))) (lambda (class-1 ident-2 l-curl-3 public-4 static-5 void-6 ident-7 l-paren-8 ident-9 l-brak-10 r-brak-11 ident-12 r-paren-13 l-curl-14 @statement-15 r-curl-16 r-curl-17) (ast-node class (:class-name (token-value ident-2)) (:line-col (token-line-col class-1)) (:parent #f) (:constructors (quote ())) (:potential-main-class #t) (:instance-vars (quote ())) (:static-vars (quote ())) (:methods (quote ())) (:static-methods (list (ast-node method (:name (token-value ident-7)) (:line-col (token-line-col public-4)) (:return-type (ast-node simple-type (:name "void"))) (:param-list (quote ())) (:static? #t) (:param-list-main (list (ast-node param (:type (ast-node array-type (:line-col (token-line-col ident-9)) (:element-type (ast-node simple-type (:line-col (token-line-col ident-9)) (:name (token-value ident-9)))))) (:line-col (token-line-col ident-9)) (:name (token-value ident-12))))) (:local-vars (quote ())) (:statements (list @statement-15))))))) (lambda (class ident @class-body) (ast-node class (:line-col (token-line-col class)) (:class-name (token-value ident)) (:parent #f) (:instance-vars (list-ref @class-body 0)) (:static-vars (list-ref @class-body 2)) (:methods (list-ref @class-body 1)) (:static-methods (list-ref @class-body 3)) (:constructors (list-ref @class-body 4)))) (lambda (class ident-name extends ident-parent @class-body) (ast-node class (:line-col (token-line-col class)) (:class-name (token-value ident-name)) (:parent (token-value ident-parent)) (:instance-vars (list-ref @class-body 0)) (:static-vars (list-ref @class-body 2)) (:methods (list-ref @class-body 1)) (:static-methods (list-ref @class-body 3)) (:constructors (list-ref @class-body 4)))) (lambda (x @class-statement-block y) (let ((vars (filter-map (lambda (x) (and (eqv? (car x) (quote var)) (cdr x))) @class-statement-block)) (s-vars (filter-map (lambda (x) (and (eqv? (car x) (quote static-var)) (cdr x))) @class-statement-block)) (methods (filter-map (lambda (x) (and (eqv? (car x) (quote method)) (not (@ast (cdr x) :static?)) (cdr x))) @class-statement-block)) (s-methods (filter-map (lambda (x) (and (eqv? (car x) (quote method)) (@ast (cdr x) :static?) (cdr x))) @class-statement-block)) (ctors (filter-map (lambda (x) (and (eqv? (quote ctor) (car x)) (cdr x))) @class-statement-block))) (list vars methods s-vars s-methods ctors))) (lambda (x y) (list (quote ()) (quote ()) (quote ()))) (lambda (x) (list x)) (lambda (x y) (append x (list y))) (lambda (@var) (cons (quote var) @var)) (lambda (@static-var) (cons (quote static-var) @static-var)) (lambda (@method) (cons (quote method) @method)) (lambda (@constructor) (cons (quote ctor) @constructor)) (lambda (v) (list v)) (lambda (@var-block @var) (append @var-block (list @var))) (lambda (@type ident s-colon) (ast-node var (:line-col (@ast @type :line-col)) (:name (token-value ident)) (:type @type))) (lambda (x @type ident s-colon) (ast-node static-var (:line-col (token-line-col x)) (:name (token-value ident)) (:type @type))) (lambda (x ident y z @method-body) (ast-node constructor (:line-col (list-ref x 2)) (:param-list (quote ())) (:static? #t) (:return-type (ast-node user-type (:name (token-value ident)))) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (--x ident --y @param-list --z @method-body) (ast-node constructor (:line-col (list-ref --x 2)) (:param-list @param-list) (:static? #t) (:return-type (ast-node user-type (:name (token-value ident)))) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (@method-start r-paren @method-body) (ast-node method (:line-col (list-ref @method-start 2)) (:name (list-ref @method-start 1)) (:param-list (quote ())) (:return-type (list-ref @method-start 0)) (:static? (list-ref @method-start 3)) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (@method-start @param-list r-paren @method-body) (ast-node method (:line-col (list-ref @method-start 2)) (:name (list-ref @method-start 1)) (:param-list @param-list) (:return-type (list-ref @method-start 0)) (:static? (list-ref @method-start 3)) (:local-vars (list-ref @method-body 0)) (:statements (list-ref @method-body 1)))) (lambda (--sasm-impl --public --static @type method-name@method-ident --l-paren @param-list --r-paren --= sasm-ident@method-ident --s-colon) (ast-node method (:sasm-impl-no-codegen #t) (:static-method-alternate-identifier (token-value sasm-ident@method-ident)) (:line-col (token-line-col --sasm-impl)) (:name (token-value method-name@method-ident)) (:param-list @param-list) (:return-type @type) (:static? #t) (:local-vars (quote ())) (:statements (quote ())))) (lambda (--sasm-impl --public --static @type method-name@method-ident --l-paren --r-paren --= sasm-ident@method-ident --s-colon) (ast-node method (:sasm-impl-no-codegen #t) (:static-method-alternate-identifier (token-value sasm-ident@method-ident)) (:line-col (token-line-col --sasm-impl)) (:name (token-value method-name@method-ident)) (:param-list (quote ())) (:return-type @type) (:static? #t) (:local-vars (quote ())) (:statements (quote ())))) (lambda (x @type ident y) (list @type (token-value ident) (token-line-col x) #f)) (lambda (x y @type ident z) (list @type (token-value ident) (token-line-col x) #t)) (lambda (x) x) (lambda (x) x) (lambda (x) (list x)) (lambda (a comma b) (append a (list b))) (lambda (@type ident) (ast-node param (:line-col (@ast @type :line-col)) (:type @type) (:name (token-value ident)))) (lambda (l-curl @var-block @statement-block r-curl) (list @var-block @statement-block)) (lambda (l-curl @statement-block r-curl) (list (quote ()) @statement-block)) (lambda (l-curl r-curl) (list (quote ()) (quote ()))) (lambda (x) (list x)) (lambda (x y) (append x (list y))) (lambda (x y z) (ast-node array-type (:line-col (token-line-col x)) (:element-type (ast-node simple-type (:name "int"))))) (lambda (x y z) (ast-node array-type (:line-col (token-line-col x)) (:element-type (ast-node simple-type (:name "char"))))) (lambda (ident y z) (ast-node array-type (:line-col (token-line-col ident)) (:element-type (ast-node user-type (:name (token-value ident)))))) (lambda (x) (ast-node simple-type (:line-col (token-line-col x)) (:name "boolean"))) (lambda (x) (ast-node simple-type (:line-col (token-line-col x)) (:name "int"))) (lambda (x) (ast-node simple-type (:line-col (token-line-col x)) (:name "char"))) (lambda (ident) (ast-node user-type (:line-col (token-line-col ident)) (:name (token-value ident)))) (lambda (x y) (ast-node compound-statement (:line-col (token-line-col x)) (:statements (quote ())))) (lambda (x @statement-block z) (ast-node compound-statement (:line-col (token-line-col x)) (:statements @statement-block))) (lambda (if-tok l-paren @exp r-paren @statement-consequent else @statement-antecedent) (ast-node if-statement (:line-col (token-line-col if-tok)) (:condition @exp) (:consequent @statement-consequent) (:antecedent @statement-antecedent))) (lambda (while l-paren @exp r-paren @statement) (ast-node while-statement (:line-col (token-line-col while)) (:condition @exp) (:body @statement))) (lambda (x y @exp z w) (ast-node print-statement (:line-col (token-line-col x)) (:exp @exp))) (lambda (ident x @exp y) (ast-node assignment-statement (:line-col (token-line-col ident)) (:ident (token-value ident)) (:exp @exp))) (lambda (ident x @index-exp y z @value-exp w) (ast-node array-assignment-statement (:line-col (token-line-col ident)) (:ident (token-value ident)) (:index-exp @index-exp) (:value-exp @value-exp))) (lambda (r @exp s) (ast-node return-statement (:line-col (token-line-col r)) (:exp @exp))) (lambda (r s) (ast-node return-statement (:line-col (token-line-col r)))) (lambda (x) x) (lambda (x) x) (lambda (@exp-logical foo @exp-comparison) (ast-node and-expression (:line-col (token-line-col foo)) (:left @exp-logical) (:right @exp-comparison))) (lambda (x) x) (lambda (@exp-term-left foo @exp-term-right) (ast-node less-than-expression (:line-col (token-line-col foo)) (:left @exp-term-left) (:right @exp-term-right))) (lambda (@exp-term-left foo @exp-term-right) (ast-node equal-to-expression (:line-col (token-line-col foo)) (:left @exp-term-left) (:right @exp-term-right))) (lambda (x) x) (lambda (@exp-term foo @exp-factor) (ast-node add-expression (:line-col (token-line-col foo)) (:left @exp-term) (:right @exp-factor))) (lambda (@exp-term foo @exp-factor) (ast-node subtract-expression (:line-col (token-line-col foo)) (:left @exp-term) (:right @exp-factor))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-or)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-and)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-xor)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (x) x) (lambda (@exp-factor foo @exp-elem) (ast-node multiply-expression (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-arith-rshift)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-lshift)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (@exp-factor foo @exp-elem) (ast-node int-binop-expression (:op (quote bit-rshift)) (:line-col (token-line-col foo)) (:left @exp-factor) (:right @exp-elem))) (lambda (x) x) (lambda (x) x) (lambda (foo @exp-elem) (ast-node not-expression (:line-col (token-line-col foo)) (:exp @exp-elem))) (lambda (foo @exp-elem) (ast-node int-unop-expression (:op (quote bit-not)) (:line-col (token-line-col foo)) (:exp @exp-elem))) (lambda (@exp-ref foo-1 @exp foo-2) (ast-node array-ref-expression (:line-col (@ast @exp-ref :line-col)) (:array-exp @exp-ref) (:index-exp @exp))) (lambda (@exp-ref foo-1 foo-2) (ast-node length-expression (:line-col (@ast @exp-ref :line-col)) (:exp @exp-ref))) (lambda (@exp-ref foo-1 ident foo-2 foo-3) (ast-node method-call-expression (:line-col (@ast @exp-ref :line-col)) (:object @exp-ref) (:method-name (token-value ident)) (:arg-list (quote ())))) (lambda (@exp-ref foo-1 ident foo-2 @exp-list foo-3) (ast-node method-call-expression (:line-col (@ast @exp-ref :line-col)) (:object @exp-ref) (:method-name (token-value ident)) (:arg-list @exp-list))) (lambda (x) x) (lambda (x) (ast-node number-constant-expression (:line-col (token-line-col x)) (:value (token-value x)))) (lambda (x) (ast-node boolean-constant-expression (:line-col (token-line-col x)) (:value "true") (:scheme-value #t))) (lambda (y) (ast-node boolean-constant-expression (:line-col (token-line-col y)) (:value "false") (:scheme-value #f))) (lambda (c) (ast-node char-constant-expression (:line-col (token-line-col c)) (:value (token-value c)))) (lambda (s) (ast-node new-object-expression (:line-col (token-line-col s)) (:class-name "String") (:arg-list (list (ast-node string-constant-expression (:line-col (token-line-col s)) (:value (token-value s))))))) (lambda (y) (ast-node variable-expression (:line-col (token-line-col y)) (:ident (token-value y)))) (lambda (y) (ast-node this-expression (:line-col (token-line-col y)))) (lambda (foo-1 foo-2 foo-3 @exp foo-4) (ast-node new-array-expression (:line-col (token-line-col foo-1)) (:element-type (ast-node simple-type (:name "int"))) (:length @exp))) (lambda (foo-1 foo-2 foo-3 @exp foo-4) (ast-node new-array-expression (:line-col (token-line-col foo-1)) (:element-type (ast-node simple-type (:name "char"))) (:length @exp))) (lambda (foo-1 @ident foo-3 @exp foo-4) (ast-node new-array-expression (:line-col (token-line-col foo-1)) (:element-type (ast-node user-type (:name (token-value @ident)))) (:length @exp))) (lambda (foo-1 ident foo-2 foo-3) (ast-node new-object-expression (:line-col (token-line-col foo-1)) (:class-name (token-value ident)) (:arg-list (quote ())))) (lambda (foo:new ident foo:l-paren @exp-list foo:r-paren) (ast-node new-object-expression (:line-col (token-line-col foo:new)) (:class-name (token-value ident)) (:arg-list @exp-list))) (lambda (foo-1 @exp foo-2) @exp) (lambda (x) (list x)) (lambda (x y z) (append x (list z))))) +(define (minijava-parse-input input) (run-parse (quote ((@goal @program) (@program @main-class) (@program @main-class @class-list) (@class-list @class) (@class-list @class-list @class) (@main-class class ident l-curl public static void ident l-paren ident l-brak r-brak ident r-paren l-curl @statement r-curl r-curl) (@class class ident @class-body) (@class class ident extends ident @class-body) (@class-body l-curl @class-statement-block r-curl) (@class-body l-curl r-curl) (@class-statement-block @class-statement) (@class-statement-block @class-statement-block @class-statement) (@class-statement @var) (@class-statement @static-var) (@class-statement @method) (@class-statement @constructor) (@var-block @var) (@var-block @var-block @var) (@var @type ident s-colon) (@static-var static @type ident s-colon) (@constructor public ident l-paren r-paren @method-body) (@constructor public ident l-paren @param-list r-paren @method-body) (@method @method-start r-paren @method-body) (@method @method-start @param-list r-paren @method-body) (@method --sasm-impl public static @type @method-ident l-paren @param-list r-paren = ident s-colon) (@method --sasm-impl public static @type @method-ident l-paren r-paren = ident s-colon) (@method-start public @type @method-ident l-paren) (@method-start public static @type @method-ident l-paren) (@method-ident ident) (@method-ident length) (@param-list @param) (@param-list @param-list comma @param) (@param @type ident) (@method-body l-curl @var-block @statement-block r-curl) (@method-body l-curl @statement-block r-curl) (@method-body l-curl r-curl) (@statement-block @statement) (@statement-block @statement-block @statement) (@type int l-brak r-brak) (@type char l-brak r-brak) (@type ident l-brak r-brak) (@type boolean) (@type int) (@type char) (@type ident) (@statement l-curl r-curl) (@statement l-curl @statement-block r-curl) (@statement if l-paren @exp r-paren @statement else @statement) (@statement while l-paren @exp r-paren @statement) (@statement system-out-println l-paren @exp r-paren s-colon) (@statement ident = @exp s-colon) (@statement ident l-brak @exp r-brak = @exp s-colon) (@statement return @exp s-colon) (@statement return s-colon) (@exp @exp-logical) (@exp-logical @exp-comparison) (@exp-logical @exp-logical && @exp-comparison) (@exp-comparison @exp-term) (@exp-comparison @exp-term < @exp-term) (@exp-comparison @exp-term == @exp-term) (@exp-term @exp-factor) (@exp-term @exp-term + @exp-factor) (@exp-term @exp-term - @exp-factor) (@exp-factor @exp-factor pipe @exp-elem) (@exp-factor @exp-factor & @exp-elem) (@exp-factor @exp-factor ^ @exp-elem) (@exp-factor @exp-elem) (@exp-factor @exp-factor * @exp-elem) (@exp-factor @exp-factor >> @exp-elem) (@exp-factor @exp-factor << @exp-elem) (@exp-factor @exp-factor >>> @exp-elem) (@exp-elem @exp-array) (@exp-elem @exp-ref) (@exp-elem bang @exp-elem) (@exp-elem ~ @exp-elem) (@exp-array @exp-ref l-brak @exp r-brak) (@exp-ref @exp-ref dot length) (@exp-ref @exp-ref dot @method-ident l-paren r-paren) (@exp-ref @exp-ref dot @method-ident l-paren @exp-list r-paren) (@exp-ref @exp-trivial) (@exp-trivial number) (@exp-trivial true) (@exp-trivial false) (@exp-trivial char-literal) (@exp-trivial string-literal) (@exp-trivial ident) (@exp-trivial this) (@exp-trivial new int l-brak @exp r-brak) (@exp-trivial new char l-brak @exp r-brak) (@exp-trivial new ident l-brak @exp r-brak) (@exp-trivial new ident l-paren r-paren) (@exp-trivial new ident l-paren @exp-list r-paren) (@exp-trivial l-paren @exp r-paren) (@exp-list @exp) (@exp-list @exp-list comma @exp))) (quote (class ident l-curl public static void l-paren l-brak r-brak r-paren r-curl extends s-colon --sasm-impl = length comma int char boolean if else while system-out-println return && < == + - pipe & ^ * >> << >>> bang ~ dot number true false char-literal string-literal this new $)) (quote (@goal @program @class-list @main-class @class @class-body @class-statement-block @class-statement @var-block @var @static-var @constructor @method @method-start @method-ident @param-list @param @method-body @statement-block @type @statement @exp @exp-logical @exp-comparison @exp-term @exp-factor @exp-elem @exp-array @exp-ref @exp-trivial @exp-list)) (quote #(#((s . 3) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (a . #f)) #((s . 6) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 1)) #(#f (s . 7) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((s . 6) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 2)) #((r . 3) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 3)) #(#f (s . 9) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 10) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 4) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 4)) #(#f #f (s . 12) #f #f #f #f #f #f #f #f (s . 13) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f (s . 14) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 6) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 6)) #(#f (s . 21) #f (s . 27) (s . 24) #f #f #f #f #f (s . 30) #f #f (s . 28) #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 31) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f (s . 32) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f (s . 27) (s . 24) #f #f #f #f #f (s . 33) #f #f (s . 28) #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 10) #f (r . 10) (r . 10) #f #f #f #f #f (r . 10) #f #f (r . 10) #f #f #f (r . 10) (r . 10) (r . 10) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 12) #f (r . 12) (r . 12) #f #f #f #f #f (r . 12) #f #f (r . 12) #f #f #f (r . 12) (r . 12) (r . 12) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 35) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 42) #f #f #f #f #f (s . 36) #f #f #f #f #f #f #f (r . 42) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 43) #f #f #f #f #f (s . 37) #f #f #f #f #f #f #f (r . 43) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 44) #f #f #f #f #f (s . 38) #f #f #f #f #f #f #f (r . 44) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 41) #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 41) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 13) #f (r . 13) (r . 13) #f #f #f #f #f (r . 13) #f #f (r . 13) #f #f #f (r . 13) (r . 13) (r . 13) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 14) #f (r . 14) (r . 14) #f #f #f #f #f (r . 14) #f #f (r . 14) #f #f #f (r . 14) (r . 14) (r . 14) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f #f #f #f #f #f #f (s . 40) #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 45) #f #f (s . 46) #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f (s . 47) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 15) #f (r . 15) (r . 15) #f #f #f #f #f (r . 15) #f #f (r . 15) #f #f #f (r . 15) (r . 15) (r . 15) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 9) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 9)) #(#f #f (s . 12) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f (s . 49) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 8) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 8)) #(#f (r . 11) #f (r . 11) (r . 11) #f #f #f #f #f (r . 11) #f #f (r . 11) #f #f #f (r . 11) (r . 11) (r . 11) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 50) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 51) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 52) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 53) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 54) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 56) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 57) #f #f #f #f #f #f (s . 58) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 30) #f #f #f #f #f #f (r . 30) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 59) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 61) #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 62) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 44) #f #f #f #f (s . 63) (s . 38) #f #f #f #f #f #f #f (r . 44) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f (s . 65) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 7) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 7)) #(#f (s . 66) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 18) (r . 18) (r . 18) (r . 18) #f #f #f #f #f (r . 18) #f #f (r . 18) #f #f #f (r . 18) (r . 18) (r . 18) (r . 18) #f (r . 18) (r . 18) (r . 18) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 38) #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 38) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 39) #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 39) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 40) #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 40) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 67) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 22) #f (r . 22) (r . 22) #f #f #f #f #f (r . 22) #f #f (r . 22) #f #f #f (r . 22) (r . 22) (r . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 70) (s . 73) #f #f #f #f #f #f #f (s . 78) #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 56) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 32) #f #f #f #f #f #f (r . 32) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 81) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (r . 28) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (r . 29) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f #f #f #f #f #f #f (s . 82) #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 61) #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 62) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 86) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 19) #f (r . 19) (r . 19) #f #f #f #f #f (r . 19) #f #f (r . 19) #f #f #f (r . 19) (r . 19) (r . 19) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 70) (s . 73) #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 16) (r . 16) #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 16) (r . 16) (r . 16) (r . 16) #f (r . 16) (r . 16) (r . 16) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 44) #f #f #f #f #f (s . 89) #f #f #f #f #f #f (s . 90) (r . 44) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f (s . 91) #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 36) (r . 36) #f #f #f #f #f #f #f (r . 36) #f #f #f #f #f #f #f #f #f (r . 36) #f (r . 36) (r . 36) (r . 36) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f (s . 94) #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 96) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 97) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 98) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f (s . 119) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (r . 35) #f (r . 35) (r . 35) #f #f #f #f #f (r . 35) #f #f (r . 35) #f #f #f (r . 35) (r . 35) (r . 35) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 23) #f (r . 23) (r . 23) #f #f #f #f #f (r . 23) #f #f (r . 23) #f #f #f (r . 23) (r . 23) (r . 23) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 31) #f #f #f #f #f #f (r . 31) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 26) #f #f #f #f #f #f #f (r . 26) #f #f #f #f #f #f #f (r . 26) (r . 26) (r . 26) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 56) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 121) #f #f #f #f #f #f (s . 58) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 122) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 61) #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 62) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 124) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f (s . 125) #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 17) (r . 17) #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 17) (r . 17) (r . 17) (r . 17) #f (r . 17) (r . 17) (r . 17) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f (s . 53) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (r . 34) #f (r . 34) (r . 34) #f #f #f #f #f (r . 34) #f #f (r . 34) #f #f #f (r . 34) (r . 34) (r . 34) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 37) (r . 37) #f #f #f #f #f #f #f (r . 37) #f #f #f #f #f #f #f #f #f (r . 37) #f (r . 37) (r . 37) (r . 37) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (s . 128) #f #f #f #f #f #f (s . 90) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 45) (r . 45) #f #f #f #f #f #f #f (r . 45) #f #f #f #f #f #f #f #f #f (r . 45) (r . 45) (r . 45) (r . 45) (r . 45) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f (s . 129) #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 133) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 54) (r . 54) #f #f (r . 54) #f #f #f (r . 54) #f #f #f #f #f #f #f #f (s . 134) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 55) (r . 55) #f #f (r . 55) #f #f #f (r . 55) #f #f #f #f #f #f #f #f (r . 55) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 57) (r . 57) #f #f (r . 57) #f #f #f (r . 57) #f #f #f #f #f #f #f #f (r . 57) (s . 137) (s . 138) (s . 135) (s . 136) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 60) (r . 60) #f #f (r . 60) #f #f #f (r . 60) #f #f #f #f #f #f #f #f (r . 60) (r . 60) (r . 60) (r . 60) (r . 60) (s . 139) (s . 140) (s . 141) (s . 142) (s . 143) (s . 144) (s . 145) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 66) (r . 66) #f #f (r . 66) #f #f #f (r . 66) #f #f #f #f #f #f #f #f (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) (r . 66) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 71) (r . 71) #f #f (r . 71) #f #f #f (r . 71) #f #f #f #f #f #f #f #f (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) (r . 71) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (s . 146) (r . 72) (r . 72) #f #f (r . 72) #f #f #f (r . 72) #f #f #f #f #f #f #f #f (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) (r . 72) #f #f (s . 147) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 79) (r . 79) (r . 79) #f #f (r . 79) #f #f #f (r . 79) #f #f #f #f #f #f #f #f (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) (r . 79) #f #f (r . 79) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 80) (r . 80) (r . 80) #f #f (r . 80) #f #f #f (r . 80) #f #f #f #f #f #f #f #f (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) (r . 80) #f #f (r . 80) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 81) (r . 81) (r . 81) #f #f (r . 81) #f #f #f (r . 81) #f #f #f #f #f #f #f #f (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) (r . 81) #f #f (r . 81) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 82) (r . 82) (r . 82) #f #f (r . 82) #f #f #f (r . 82) #f #f #f #f #f #f #f #f (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) (r . 82) #f #f (r . 82) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 83) (r . 83) (r . 83) #f #f (r . 83) #f #f #f (r . 83) #f #f #f #f #f #f #f #f (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) (r . 83) #f #f (r . 83) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 84) (r . 84) (r . 84) #f #f (r . 84) #f #f #f (r . 84) #f #f #f #f #f #f #f #f (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) (r . 84) #f #f (r . 84) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 85) (r . 85) (r . 85) #f #f (r . 85) #f #f #f (r . 85) #f #f #f #f #f #f #f #f (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) (r . 85) #f #f (r . 85) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 86) (r . 86) (r . 86) #f #f (r . 86) #f #f #f (r . 86) #f #f #f #f #f #f #f #f (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) (r . 86) #f #f (r . 86) #f #f #f #f #f #f #f #f) #(#f (s . 150) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 148) (s . 149) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (r . 53) (r . 53) #f #f #f #f #f #f #f (r . 53) #f #f #f #f #f #f #f #f #f (r . 53) (r . 53) (r . 53) (r . 53) (r . 53) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 20) #f (r . 20) (r . 20) #f #f #f #f #f (r . 20) #f #f (r . 20) #f #f #f (r . 20) (r . 20) (r . 20) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 56) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 27) #f #f #f #f #f #f #f (r . 27) #f #f #f #f #f #f #f (r . 27) (r . 27) (r . 27) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 155) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (s . 156) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 33) #f (r . 33) (r . 33) #f #f #f #f #f (r . 33) #f #f (r . 33) #f #f #f (r . 33) (r . 33) (r . 33) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 157) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 158) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (r . 46) (r . 46) #f #f #f #f #f #f #f (r . 46) #f #f #f #f #f #f #f #f #f (r . 46) (r . 46) (r . 46) (r . 46) (r . 46) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 159) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 160) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 161) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 52) (r . 52) #f #f #f #f #f #f #f (r . 52) #f #f #f #f #f #f #f #f #f (r . 52) (r . 52) (r . 52) (r . 52) (r . 52) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 61) #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 175) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (s . 177) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (s . 178) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 180) (s . 179) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 181) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 73) (r . 73) #f #f (r . 73) #f #f #f (r . 73) #f #f #f #f #f #f #f #f (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) (r . 73) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 74) (r . 74) #f #f (r . 74) #f #f #f (r . 74) #f #f #f #f #f #f #f #f (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) (r . 74) #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 21) #f (r . 21) (r . 21) #f #f #f #f #f (r . 21) #f #f (r . 21) #f #f #f (r . 21) (r . 21) (r . 21) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 21) #f #f #f #f #f #f #f (s . 183) #f #f #f #f #f #f #f (s . 19) (s . 20) (s . 22) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 184) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 185) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 50) (r . 50) #f #f #f #f #f #f #f (r . 50) #f #f #f #f #f #f #f #f #f (r . 50) (r . 50) (r . 50) (r . 50) (r . 50) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 188) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 56) (r . 56) #f #f (r . 56) #f #f #f (r . 56) #f #f #f #f #f #f #f #f (r . 56) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 61) (r . 61) #f #f (r . 61) #f #f #f (r . 61) #f #f #f #f #f #f #f #f (r . 61) (r . 61) (r . 61) (r . 61) (r . 61) (s . 139) (s . 140) (s . 141) (s . 142) (s . 143) (s . 144) (s . 145) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 62) (r . 62) #f #f (r . 62) #f #f #f (r . 62) #f #f #f #f #f #f #f #f (r . 62) (r . 62) (r . 62) (r . 62) (r . 62) (s . 139) (s . 140) (s . 141) (s . 142) (s . 143) (s . 144) (s . 145) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 58) (r . 58) #f #f (r . 58) #f #f #f (r . 58) #f #f #f #f #f #f #f #f (r . 58) #f #f (s . 135) (s . 136) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 59) (r . 59) #f #f (r . 59) #f #f #f (r . 59) #f #f #f #f #f #f #f #f (r . 59) #f #f (s . 135) (s . 136) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 63) (r . 63) #f #f (r . 63) #f #f #f (r . 63) #f #f #f #f #f #f #f #f (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) (r . 63) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 64) (r . 64) #f #f (r . 64) #f #f #f (r . 64) #f #f #f #f #f #f #f #f (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) (r . 64) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 65) (r . 65) #f #f (r . 65) #f #f #f (r . 65) #f #f #f #f #f #f #f #f (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) (r . 65) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 67) (r . 67) #f #f (r . 67) #f #f #f (r . 67) #f #f #f #f #f #f #f #f (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) (r . 67) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 68) (r . 68) #f #f (r . 68) #f #f #f (r . 68) #f #f #f #f #f #f #f #f (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) (r . 68) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 69) (r . 69) #f #f (r . 69) #f #f #f (r . 69) #f #f #f #f #f #f #f #f (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) (r . 69) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 70) (r . 70) #f #f (r . 70) #f #f #f (r . 70) #f #f #f #f #f #f #f #f (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) (r . 70) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 189) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (r . 29) (r . 76) (r . 76) (r . 76) #f #f (r . 76) #f #f #f (r . 76) #f #f #f #f #f #f #f #f (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) (r . 76) #f #f (r . 76) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (s . 190) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f (s . 194) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f #f #f #f #f #f #f (r . 92) (r . 92) (r . 92) #f #f (r . 92) #f #f #f (r . 92) #f #f #f #f #f #f #f #f (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) (r . 92) #f #f (r . 92) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 197) #f #f #f #f #f #f (s . 58) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 198) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 199) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 201) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 48) (r . 48) #f #f #f #f #f #f #f (r . 48) #f #f #f #f #f #f #f #f #f (r . 48) (r . 48) (r . 48) (r . 48) (r . 48) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 49) (r . 49) #f #f #f #f #f #f #f (r . 49) #f #f #f #f #f #f #f #f #f (r . 49) (r . 49) (r . 49) (r . 49) (r . 49) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (r . 75) (r . 75) #f #f (r . 75) #f #f #f (r . 75) #f #f #f #f #f #f #f #f (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) (r . 75) #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f (s . 202) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f #f #f #f #f #f #f #f (s . 204) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 205) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (s . 206) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 90) (r . 90) (r . 90) #f #f (r . 90) #f #f #f (r . 90) #f #f #f #f #f #f #f #f (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) (r . 90) #f #f (r . 90) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 207) #f #f #f #f #f #f (s . 208) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 93) #f #f #f #f #f #f (r . 93) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 209) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 210) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 211) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 212) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 77) (r . 77) (r . 77) #f #f (r . 77) #f #f #f (r . 77) #f #f #f #f #f #f #f #f (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) (r . 77) #f #f (r . 77) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (s . 214) #f #f #f #f #f #f (s . 208) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 87) (r . 87) (r . 87) #f #f (r . 87) #f #f #f (r . 87) #f #f #f #f #f #f #f #f (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) (r . 87) #f #f (r . 87) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 88) (r . 88) (r . 88) #f #f (r . 88) #f #f #f (r . 88) #f #f #f #f #f #f #f #f (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) (r . 88) #f #f (r . 88) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 89) (r . 89) (r . 89) #f #f (r . 89) #f #f #f (r . 89) #f #f #f #f #f #f #f #f (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) (r . 89) #f #f (r . 89) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 91) (r . 91) (r . 91) #f #f (r . 91) #f #f #f (r . 91) #f #f #f #f #f #f #f #f (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) (r . 91) #f #f (r . 91) #f #f #f #f #f #f #f #f) #(#f (s . 113) #f #f #f #f (s . 116) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 117) (s . 118) #f (s . 108) (s . 109) (s . 110) (s . 111) (s . 112) (s . 114) (s . 115) #f) #(#f (s . 216) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 217) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (s . 218) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 51) (r . 51) #f #f #f #f #f #f #f (r . 51) #f #f #f #f #f #f #f #f #f (r . 51) (r . 51) (r . 51) (r . 51) (r . 51) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 47) (r . 47) #f #f #f #f #f #f #f (r . 47) #f #f #f #f #f #f #f #f #f (r . 47) (r . 47) (r . 47) (r . 47) (r . 47) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (r . 78) (r . 78) (r . 78) #f #f (r . 78) #f #f #f (r . 78) #f #f #f #f #f #f #f #f (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) (r . 78) #f #f (r . 78) #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (r . 94) #f #f #f #f #f #f (r . 94) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f (s . 219) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 25) #f (r . 25) (r . 25) #f #f #f #f #f (r . 25) #f #f (r . 25) #f #f #f (r . 25) (r . 25) (r . 25) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (s . 93) (s . 73) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (s . 74) #f (s . 75) (s . 76) (s . 77) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f (r . 24) #f (r . 24) (r . 24) #f #f #f #f #f (r . 24) #f #f (r . 24) #f #f #f (r . 24) (r . 24) (r . 24) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 221) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f (s . 222) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #((r . 5) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (r . 5)))) (quote #(#(#f (g . 1) #f (g . 2) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f (g . 4) #f (g . 5) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f (g . 8) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f (g . 11) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f (g . 15) (g . 16) #f (g . 17) (g . 23) (g . 29) (g . 25) (g . 26) #f #f #f #f #f (g . 18) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f (g . 34) #f (g . 17) (g . 23) (g . 29) (g . 25) (g . 26) #f #f #f #f #f (g . 18) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 39) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 41) (g . 42) #f #f (g . 43) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 44) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f (g . 48) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 55) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 60) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 64) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f (g . 68) (g . 69) #f #f #f #f #f #f #f #f (g . 71) (g . 18) (g . 72) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 79) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 80) #f #f (g . 43) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 83) (g . 42) #f #f (g . 43) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 84) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 85) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f (g . 88) #f #f #f #f #f #f #f #f (g . 87) (g . 18) (g . 72) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 92) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 95) #f (g . 72) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 99) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 120) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 123) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 92) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 126) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 127) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 92) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 130) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 131) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 132) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 151) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 152) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 153) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 154) #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 126) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 162) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 163) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 164) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 165) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 166) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 167) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 168) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 169) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 170) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 171) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 172) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 173) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 174) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 176) #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 182) (g . 42) #f #f (g . 43) #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 186) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 187) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 191) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 192) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 193) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 196) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) (g . 195)) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 200) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 196) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) (g . 203)) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 213) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 215) (g . 100) (g . 101) (g . 102) (g . 103) (g . 104) (g . 105) (g . 106) (g . 107) #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f (g . 220) #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f) #(#f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f #f))) action-table input)) +(define (minijava-parse-port input-port) (minijava-parse-input (read input-port))) +(define (minijava-parse-file filename) (call-with-input-file filename minijava-parse-port)) diff --git a/src/minijava-tokens-java.scm b/src/minijava-tokens-java.scm new file mode 100644 index 0000000..4d2ca53 --- /dev/null +++ b/src/minijava-tokens-java.scm @@ -0,0 +1,238 @@ +;; minijava-tokens-java.scm +;; +;; adapted from minijava-tokens.scm +;; +;; + +(need regex/regex) +(need regex/genlex) +(need util/list) +(need util/list) + +;; Some basic definitions to aid in building regular expressions + +(define (chars string) + string) + +(define (chars-append . args) + (apply string-append args)) + +(define (chars-without chars exclude) + (list->string (filter (lambda (char) (not (strchr exclude char))) + (string->list chars)))) + +;; The bulk of a regular expression is defining the allowable +;; characters. The following definitions of character sets will allow +;; me to compose them into other character sets + +;; alpha -> (a-z|A-Z) +(define alpha (chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")) + +;; numeric -> (0-9) +(define numeric (chars "0123456789")) + +;; whitespace -> space | carriage-return | newline | tab +(define whitespace (chars "\r\t\n ")) + +;; special characters +(define special (chars "`~!@#%^&*()-=+{[]}|:;'<>,.?/_\"")) + +;; The start character of an identifier can be an alphabet character +;; or an underscore +(define ident-start (chars-append alpha (chars "_"))) + +;; An internal identifier character can be any start character, plus +;; any numeric character. +(define ident (chars-append ident-start numeric)) + +;; These are the characters that are allowed to fall in between the +;; quotes of a string literal, *discounting* escape sequences. Escape +;; sequences and the surrounding quotes will be handled in the RE +;; definition below. +;; +(define string-chars (chars-append alpha numeric (chars-without special "\"") + (chars " "))) + +;; Characters allowed to fall inside of a "//" comment. +(define slashslash-comment-chars (chars-append alpha numeric special (chars-without whitespace "\n"))) +(define slashstar-comment-chars (chars-append alpha numeric (chars-without special "*/") whitespace)) + +;; Most of the tokens in our lexer are simple keywords. There are +;; only a few that are handled by "real" RE's. I'm defining these +;; below. +;; +;; My RE language is very similar (and I'll argue *equivalent*) to the +;; standard RE syntax taught in academic settings. However, since +;; this is Scheme and s-exp's are the most convenient representation +;; mechanism, I'm translating them into a prefix syntax. +;; +;; Standard Academic Syntax | Scheme | Notes +;; -------------------------------------+-----------------------+---------------- +;; a* | (* a) | +;; a+ | (+ a) | +;; (a | b) | (: a b) | +;; (a | the-empty-string) | (^ a) | "a is optional" +;; abc | (& a b c) | "sequencing operator" +;; abc | "abc" | "sequencing characters only" +;; 0-9 | (@ "0123456789") | *** +;; +;; +;; *** (@ "abc123@$") is shorthand for (a|b|c|1|2|3|@||$). Since this +;; is a common case and would add lots of states to the NFA for the +;; regex, expressions using this syntax are also carefully optimized. +;; + +;; == integers == +;; +;; A special note on integer constants: the leading '+' or '-' character +;; is not handled in the lexical analysis phase, but later in the parsing +;; phase. So the '+/-' is not included in this regular expression. +;; +;; Standard: +;; (0-9)+(u|U|l|L|the-empty-string) +;; +;; S-Exp: +;; (& (+ (@ "0123456789")) (^ (: u U l L))) +;; +(define integer-pattern `(& (+ (@ ,numeric)) (^ (: #\u #\U #\l #\L)))) + +;; == identifiers == +;; +;; Standard: +;; (a-z|A-Z|_)(a-z|A-Z|0-9|_)* +;; +;; S-Exp: +;; (& (@ "a...zA...Z_") (* (@ "a..zA..Z_0..9"))) +;; +(define identifier-pattern `(& (@ ,ident-start) (* (@ ,ident)))) + +;; == string literals == +;; +;; Standard: +;; "(a-z|A-Z|0-9|!|@|$|...|\(n|r|t|"|\))*" +;; +;; S-Exp: +;; (& #\" (* (: (& #\\ (@ "nrt\"\\")) (@ "a..zA..Z0..9!..."))) ") +;; +;; NOTE: Syntax for a character literal in Scheme is #\c. +;; +;; C/C++ Scheme +;; 'a' #\a +;; '#' #\# +;; '\\' #\\ +;; '\'' #\' +;; '"' #\" +;; ' ' #\space +;; '\n' #\newline +;; +(define string-pattern `(& #\" + (* (: (& #\\ (@ "0nrt\"\\")) + (@ ,string-chars))) + #\")) + +;; == char literal == +;; +;; 'a' 'b' 'c' '\'' '"' '\\' +;; +(define char-pattern `(& #\' + (: (@ ,(chars-append alpha numeric (chars " ") + (chars-without special "'"))) + (& #\\ (@ "0nrt\\'"))) + #\')) + +;; /* comments */ +;; +;; This is more-or-less a literal translation of my regular expression from homework 1. +;; +;; (define slashstar-comment-pattern `(& #\/ #\* +;; (* (@ ,(chars-append slashstar-comment-chars (chars "/")))) +;; #\* +;; (* #\*) +;; (* (& (@ ,slashstar-comment-chars) +;; (* ,(chars-append slashstar-comment-chars (chars "/"))) +;; #\* +;; (* #\*))) +;; #\/)) +(define slashstar-comment-pattern `(& "/*" + (* (& (* (@ ,(chars-append slashstar-comment-chars (chars "/")))) + (* (& (+ "*") (+ (@ ,slashstar-comment-chars)))))) + (+ "*") + "/")) + +(define tokens + `((*whitespace* (* (@ ,whitespace))) + (*comment* (& #\/ #\/ (* (@ ,slashslash-comment-chars)) #\newline)) + (*comment* ,slashstar-comment-pattern) + (--sasm-impl "__sasm_impl") + (class "class") + (super "super") + (length "length") + (extends "extends") + (new "new") + (l-paren "(") + (r-paren ")") + (l-curl "{") + (r-curl "}") + (public "public") + (static "static") + (void "void") + (l-brak "[") + (r-brak "]") + (s-colon ";") + (int "int") + (char "char") + (boolean "boolean") + (return "return") + (if "if") + (while "while") + (else "else") + (= "=") + (&& "&&") + (< "<") + (== "==") + (> ">") + (+ "+") + (- "-") + (* "*") + (dot ".") + (? "?") + (>>> ">>>") + (>> ">>") + (<< "<<") + (pipe "|") + (& "&") + (~ "~") + (^ "^") + (true "true") + (this "this") + (false "false") + (throw "throw") + (null "null") + (bang "!") + (comma ",") + (colon ":") + (percent "%") + (forward-slash "/") + (char-literal ,char-pattern) + (string-literal ,string-pattern) + (ident ,identifier-pattern) + (number ,integer-pattern) + )) + +(define minijava-lexer (generate-lexer tokens + '(*whitespace* *comment*))) + +(define lexer-filename "minijava-lexer-java.scm") + +(define (main) + (if (file-exists? lexer-filename) + (delete-file lexer-filename)) + + (call-with-output-file lexer-filename + (lambda (port) + (write-lexer minijava-lexer + 'minijava-lexer-dfa + 'minijava-lexically-analyze + port)))) + +(main) diff --git a/src/minijava-tokens.scm b/src/minijava-tokens.scm new file mode 100644 index 0000000..e394691 --- /dev/null +++ b/src/minijava-tokens.scm @@ -0,0 +1,242 @@ +;; scanner.scm +;; +;; This module uses the lexer generator to create a lexer for the +;; minijava language. First it defines some character sets, then +;; combines them into regular expressions, defines a table of token +;; types based on those regular expressions, and finally invokes the +;; scanner generator library with that table to write out the actual +;; lexer. + +;; library code declarations (analogous to header files or import +;; declarations) these are not part of any scheme standard but rather +;; my own convention +;; + +(need regex/regex) +(need regex/genlex) +(need util/list) + +;; Some basic definitions to aid in building regular expressions + +(define (chars string) + string) + +(define (chars-append . args) + (apply string-append args)) + +(define (chars-without chars exclude) + (list->string (filter (lambda (char) (not (strchr exclude char))) + (string->list chars)))) + +;; The bulk of a regular expression is defining the allowable +;; characters. The following definitions of character sets will allow +;; me to compose them into other character sets + +;; alpha -> (a-z|A-Z) +(define alpha (chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")) + +;; numeric -> (0-9) +(define numeric (chars "0123456789")) + +;; whitespace -> space | carriage-return | newline | tab +(define whitespace (chars "\r\t\n ")) + +;; special characters +(define special (chars "`~!@#%^&*()-=+{[]}|:;'<>,.?/_\"")) + +;; The start character of an identifier can be an alphabet character +;; or an underscore +(define ident-start (chars-append alpha (chars "_"))) + +;; An internal identifier character can be any start character, plus +;; any numeric character. +(define ident (chars-append ident-start numeric)) + +;; These are the characters that are allowed to fall in between the +;; quotes of a string literal, *discounting* escape sequences. Escape +;; sequences and the surrounding quotes will be handled in the RE +;; definition below. +;; +(define string-chars (chars-append alpha numeric (chars-without special "\"") + (chars " "))) + +;; Characters allowed to fall inside of a "//" comment. +(define slashslash-comment-chars (chars-append alpha numeric special (chars-without whitespace "\n"))) +(define slashstar-comment-chars (chars-append alpha numeric (chars-without special "*/") whitespace)) + +;; Most of the tokens in our lexer are simple keywords. There are +;; only a few that are handled by "real" RE's. I'm defining these +;; below. +;; +;; My RE language is very similar (and I'll argue *equivalent*) to the +;; standard RE syntax taught in academic settings. However, since +;; this is Scheme and s-exp's are the most convenient representation +;; mechanism, I'm translating them into a prefix syntax. +;; +;; Standard Academic Syntax | Scheme | Notes +;; -------------------------------------+-----------------------+---------------- +;; a* | (* a) | +;; a+ | (+ a) | +;; (a | b) | (: a b) | +;; (a | the-empty-string) | (^ a) | "a is optional" +;; abc | (& a b c) | "sequencing operator" +;; abc | "abc" | "sequencing characters only" +;; 0-9 | (@ "0123456789") | *** +;; +;; +;; *** (@ "abc123@$") is shorthand for (a|b|c|1|2|3|@||$). Since this +;; is a common case and would add lots of states to the NFA for the +;; regex, expressions using this syntax are also carefully optimized. +;; + +;; == integers == +;; +;; A special note on integer constants: the leading '+' or '-' character +;; is not handled in the lexical analysis phase, but later in the parsing +;; phase. So the '+/-' is not included in this regular expression. +;; +;; Standard: +;; (0-9)+(u|U|l|L|the-empty-string) +;; +;; S-Exp: +;; (& (+ (@ "0123456789")) (^ (: u U l L))) +;; +(define integer-pattern `(& (+ (@ ,numeric)) (^ (: #\u #\U #\l #\L)))) + +;; == identifiers == +;; +;; Standard: +;; (a-z|A-Z|_)(a-z|A-Z|0-9|_)* +;; +;; S-Exp: +;; (& (@ "a...zA...Z_") (* (@ "a..zA..Z_0..9"))) +;; +(define identifier-pattern `(& (@ ,ident-start) (* (@ ,ident)))) + +;; == string literals == +;; +;; Standard: +;; "(a-z|A-Z|0-9|!|@|$|...|\(n|r|t|"|\))*" +;; +;; S-Exp: +;; (& #\" (* (: (& #\\ (@ "nrt\"\\")) (@ "a..zA..Z0..9!..."))) ") +;; +;; NOTE: Syntax for a character literal in Scheme is #\c. +;; +;; C/C++ Scheme +;; 'a' #\a +;; '#' #\# +;; '\\' #\\ +;; '\'' #\' +;; '"' #\" +;; ' ' #\space +;; '\n' #\newline +;; +(define string-pattern `(& #\" + (* (: (& #\\ (@ "0nrt\"\\")) + (@ ,string-chars))) + #\")) + +;; == char literal == +;; +;; 'a' 'b' 'c' '\'' '"' '\\' +;; +(define char-pattern `(& #\' + (: (@ ,(chars-append alpha numeric (chars " ") + (chars-without special "'"))) + (& #\\ (@ "0nrt\\'"))) + #\')) + +;; /* comments */ +;; +;; This is more-or-less a literal translation of my regular expression from homework 1. +;; +;; (define slashstar-comment-pattern `(& #\/ #\* +;; (* (@ ,(chars-append slashstar-comment-chars (chars "/")))) +;; #\* +;; (* #\*) +;; (* (& (@ ,slashstar-comment-chars) +;; (* ,(chars-append slashstar-comment-chars (chars "/"))) +;; #\* +;; (* #\*))) +;; #\/)) +(define slashstar-comment-pattern `(& "/*" + (* (& (* (@ ,(chars-append slashstar-comment-chars (chars "/")))) + (* (& (+ "*") (+ (@ ,slashstar-comment-chars)))))) + (+ "*") + "/")) + +(define tokens + `((*whitespace* (* (@ ,whitespace))) + (*comment* (& #\/ #\/ (* (@ ,slashslash-comment-chars)) #\newline)) + (*comment* ,slashstar-comment-pattern) + (--sasm-impl "__sasm_impl") + (class "class") + (super "super") + (length "length") + (extends "extends") + (new "new") + (l-paren "(") + (r-paren ")") + (l-curl "{") + (r-curl "}") + (public "public") + (static "static") + (void "void") + (l-brak "[") + (r-brak "]") + (s-colon ";") + (int "int") + (char "char") + (boolean "boolean") + (return "return") + (if "if") + (while "while") + (else "else") + (= "=") + (&& "&&") + (< "<") + (== "==") + (> ">") + (+ "+") + (- "-") + (* "*") + (dot ".") + (? "?") + (>>> ">>>") + (>> ">>") + (<< "<<") + (pipe "|") + (& "&") + (~ "~") + (^ "^") + (true "true") + (this "this") + (false "false") + (system-out-println "System.out.println") + (fail "fail") + (bang "!") + (comma ",") + (char-literal ,char-pattern) + (string-literal ,string-pattern) + (ident ,identifier-pattern) + (number ,integer-pattern) + )) + +(define minijava-lexer (generate-lexer tokens + '(*whitespace* *comment*))) + +(define lexer-filename "minijava-lexer.scm") + +(define (main) + (if (file-exists? lexer-filename) + (delete-file lexer-filename)) + + (call-with-output-file lexer-filename + (lambda (port) + (write-lexer minijava-lexer + 'minijava-lexer-dfa + 'minijava-lexically-analyze + port)))) + +(main) diff --git a/src/need-test.scm b/src/need-test.scm new file mode 100644 index 0000000..f92ebe6 --- /dev/null +++ b/src/need-test.scm @@ -0,0 +1,3 @@ +(need tests/syntax2) + +(test-syntax foo (test-constant 1 2 3)) diff --git a/src/need.scm b/src/need.scm new file mode 100644 index 0000000..067003e --- /dev/null +++ b/src/need.scm @@ -0,0 +1,24 @@ +;; need.scm +;; +;; A bootstrap definition of the need syntax used to import libraries +;; into scheme programs. + +(define *conspiracy-root* "./") +(setenv "CONSPIRACY_ROOT" *conspiracy-root*) + +(define-syntax need + (syntax-rules () + ((_ sym) + (need-load (symbol->string 'sym))))) + +(define need-load + (let ((loaded '())) + (lambda (file) + (if (not (member file loaded)) + (begin (set! loaded (cons file loaded)) + (let ((fname (string-append file ".scm"))) + (if (file-exists? fname) + (begin + (load fname)) + (begin + (load (string-append *conspiracy-root* fname)))))))))) diff --git a/src/needc-ts.scm b/src/needc-ts.scm new file mode 100644 index 0000000..fa079f5 --- /dev/null +++ b/src/needc-ts.scm @@ -0,0 +1,2 @@ +(define *argv* (list->vector (cons "scheme" *args*))) +(load "needc.scm") diff --git a/src/needc.scm b/src/needc.scm new file mode 100644 index 0000000..85a73e2 --- /dev/null +++ b/src/needc.scm @@ -0,0 +1,549 @@ +;; needc.scm +;; +;; pre-compiler tool for the (need foo/bar/baz) special-form. +;; +;; Supports (need x/y/z) syntax, and read-file-into-list-at-compile-time. + +(define *needc-version* "generated by needc 01-20-2019 0.3") +(define *modules* '()) +(define *root* "./") +(define *flat-module-names* #f) +(define *windows-mode* #f) +(define *expand-mode* #f) +(define *dir-sep* "/") + +(define *output-fs* #f) +(define *output-modified* #f) + +(define (read-fs file) + (let ((s (stat file))) + (cons s file))) + +(define (fs-exists? fs) + (and fs (pair? fs) (car fs))) + +(define (fs-mod-time fs) + (and (fs-exists? fs) + (vector-ref (car fs) 9))) + +(define (fs-newer? fs-a fs-b) + (and (fs-exists? fs-a) + (fs-exists? fs-b) + (>= (fs-mod-time fs-a) + (fs-mod-time fs-b)))) + +(define (accumulate-modified! file-name) + (if (not (fs-exists? *output-fs*)) + (set! *output-modified* #t) + (let ((fs (read-fs file-name))) + ;; (display "newer? ") + ;; (display file-name) + ;; (display " ") + ;; (display (fs-newer? fs *output-fs*)) + ;; (newline) + (if (fs-newer? fs *output-fs*) + (set! *output-modified* #t))))) + +(define (rfilact module) + (let ((file-name (string-append *root* module))) + (accumulate-modified! file-name) + (let ((in (open-input-file file-name))) + (let loop ((result '())) + (let ((obj (read in))) + (if (eof-object? obj) + (cons 'quote (list result)) + (loop (append result (list obj))))))))) + +(define (evaluate-rfilact code) + (cond ((and (pair? code) + (eqv? 'read-file-into-list-at-compile-time (car code)) + (pair? (cdr code)) + (string? (car (cdr code))) + (null? (cdr (cdr code)))) + (rfilact (car (cdr code)))) + ((pair? code) + (cons (evaluate-rfilact (car code)) + (evaluate-rfilact (cdr code)))) + (else + code))) + +(define (module-loaded? module-name) + (define (iter modules) + (if (null? modules) + #f + (or (eqv? (car modules) module-name) + (iter (cdr modules))))) + (iter *modules*)) + +(define (load-module-port module-name input-port output-port) + (let loop ((obj (read input-port))) + (if (eof-object? obj) + #t + (begin + (cond ((and (pair? obj) + (eqv? 'need (car obj)) + (pair? (cdr obj)) + (symbol? (car (cdr obj))) + (null? (cdr (cdr obj)))) + (load-module! (car (cdr obj)) output-port) + (display ";; " output-port) + (display module-name output-port) + (newline output-port) + ) + (else + (let ((rewrite-obj (evaluate-rfilact obj))) + (write rewrite-obj output-port) + (newline output-port)))) + (loop (read input-port)))))) + +(define (load-module-file module-name file-name output-port) + (display ";; load-module " output-port) + (display module-name output-port) + (display " " output-port) + (display file-name output-port) + (newline output-port) + (let ((in (open-input-file file-name))) + (load-module-port module-name in output-port) + (close-input-port in) + )) + +(define (replace-characters-in-string string a b) + (list->string (map (lambda (char) + (cond ((char=? a char) b) + (else char))) + (string->list string)))) + +(define (flatten-path-to-file-name path) + (replace-characters-in-string path #\/ #\-)) + +(define (get-sasm-file-name path) + (replace-extension (flatten-path-to-file-name path) ".sasm")) + +(define (get-sasm-opt-file-name path) + (replace-extension (flatten-path-to-file-name path) ".sasm-opt")) + +(define (get-asm-file-name path) + (replace-extension (flatten-path-to-file-name path) ".asm")) + +(define (get-obj-file-name path) + (replace-extension (flatten-path-to-file-name path) ".obj")) + +(define (get-archive-file-name path) + (replace-extension (flatten-path-to-file-name path) ".a")) + +(define (env-var var-name) + (if *windows-mode* + (string-append "%" var-name "%") + (string-append "$" var-name))) + +(define (module-name-to-path module-name) + (let ((path (symbol->string module-name))) + (if *flat-module-names* + (replace-characters-in-string path #\/ #\-) + path))) + +(define (load-module! module-name output-port) + (if (not (module-loaded? module-name)) + (begin + (set! *modules* (cons module-name *modules*)) + (let ((file-name (string-append *root* + (module-name-to-path module-name) + ".scm"))) + (display ";; loading ") + (display file-name) + (newline) + (load-module-file module-name file-name output-port) + (accumulate-modified! file-name) + ) + ) + )) + +(define (string-starts-with? s suffix) + (and (< (string-length suffix) (string-length s)) + (string=? (substring s 0 (string-length suffix)) + suffix))) + +(define (string-last-index-of string char) + (let ((rest (member char (reverse (string->list string))))) + (if rest + (- (length rest) 1) + -1))) + +(define (replace-extension file-name new-extension) + (define (get-suffix) + (if (string-starts-with? new-extension ".") + new-extension + (string-append "." new-extension))) + + (let ((dot-index (string-last-index-of file-name #\.))) + (if (> dot-index -1) + (string-append (substring file-name 0 dot-index) + (get-suffix)) + (string-append file-name + (get-suffix))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Generate script mode + +(define (generate-script-port module-name input-port output-port) + (let loop ((obj (read input-port))) + (if (eof-object? obj) + #t + (begin + (cond ((and (pair? obj) + (eqv? 'need (car obj)) + (pair? (cdr obj)) + (symbol? (car (cdr obj))) + (null? (cdr (cdr obj)))) + (generate-script! (car (cdr obj)) output-port) + ) + (else #t)) + (loop (read input-port)))))) + +(define (generate-script-file module-name file-name output-port) + (define (emit . args) + (for-each (lambda (arg) (display arg output-port)) + args)) + (define (emit-line . args) + (apply emit args) + (newline output-port)) + (let ((port (open-input-file file-name))) + (generate-script-port module-name port output-port) + (display (string-append (if *windows-mode* + "@echo ;; compiling " + "@echo ';; compiling ") + file-name + (if *windows-mode* + "" + "'")) + output-port) + (newline output-port) + (emit-line (env-var "SCHEMEC") + " " + file-name + " --outdir " + (env-var "OUTDIR") + " --conspiracy" + (if *expand-mode* + " --expand-only" + (if (= *generate-script-depth* 1) + "" + " --no-entry"))) + (if *windows-mode* + (emit-line "@if not \"%errorlevel%\"==\"0\" exit /b 1")) + (if (not *expand-mode*) + (begin + (emit-line (env-var "SASMOPT") + " " + (env-var "OUTDIR") + *dir-sep* + (get-sasm-file-name file-name) + " --out=" + (env-var "OUTDIR") + *dir-sep* + (get-sasm-opt-file-name file-name) + " --cheap") + (if *windows-mode* + (emit-line "@if not \"%errorlevel%\"==\"0\" exit /b 1")))) + + (if (not *expand-mode*) + (begin + (emit-line (env-var "SASMC") + " " + (env-var "OUTDIR") + *dir-sep* + (get-sasm-opt-file-name file-name) + " --out=" + (env-var "OUTDIR") + *dir-sep* + (get-asm-file-name file-name)) + (if *windows-mode* + (emit-line "@if not \"%errorlevel%\"==\"0\" exit /b 1")))) + + (if (not *expand-mode*) + (begin + (emit-line "nasm -fwin32 " (env-var "OUTDIR") *dir-sep* + (get-asm-file-name file-name) + " -o " (env-var "OUTDIR") *dir-sep* + (get-obj-file-name file-name)) + (if *windows-mode* + (emit-line "@if not \"%errorlevel%\"==\"0\" exit /b 1")) + + (if (not (= *generate-script-depth* 1)) + (begin + (emit-line "ar rcs " (env-var "OUTDIR") *dir-sep* "lib" + (module-name-to-path *generate-script-main-module*) + ".a " (env-var "OUTDIR") *dir-sep* + (get-obj-file-name file-name)) + + (emit-line "@if not \"%errorlevel%\"==\"0\" exit /b 1") + )) + )) + + (close-input-port port) + )) + +(define *generate-script-depth* 0) +(define *generate-script-main-module* #f) +(define (generate-script! module-name output-port) + (if (not (module-loaded? module-name)) + (begin + (set! *generate-script-depth* (+ 1 *generate-script-depth*)) + (set! *modules* (cons module-name *modules*)) + (let ((file-name (string-append (symbol->string module-name) + ".scm"))) + (generate-script-file module-name file-name output-port) + (accumulate-modified! file-name)) + (set! *generate-script-depth* (- *generate-script-depth* 1)) + ) + )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Generate makefile mode + +(define (generate-makefile-port module-name input-port output-port) + (let loop ((obj (read input-port)) + (deps '())) + (if (eof-object? obj) + (reverse deps) + (begin + (cond ((and (pair? obj) + (eqv? 'need (car obj)) + (pair? (cdr obj)) + (symbol? (car (cdr obj))) + (null? (cdr (cdr obj)))) + (generate-makefile! (car (cdr obj)) output-port) + (loop (read input-port) + (cons (car (cdr obj)) deps))) + (else (loop (read input-port) + deps))))))) + +(define (generate-makefile-dep-symbol-name module-name) + (let* ((str (symbol->string module-name)) + (repl1 (replace-characters-in-string str #\- #\_)) + (repl2 (replace-characters-in-string repl1 #\/ #\_))) + (string-append "deps_of_" repl2))) + +(define (generate-makefile-file module-name file-name output-port) + (define (emit . args) + (for-each (lambda (arg) (display arg output-port)) + args)) + (define (emit-line . args) + (apply emit args) + (newline output-port)) + (let* ((port (open-input-file file-name)) + (tab-char (integer->char 9)) + (tab-string (string tab-char)) + (deps-symbol (generate-makefile-dep-symbol-name module-name)) + (deps (generate-makefile-port module-name port output-port))) + + (if (and *expand-mode* + (not (null? deps))) + (begin + (emit-line "## dependencies of " file-name) + (emit-line deps-symbol "=" #\\) + (for-each (lambda (dep) + (emit-line " " dep ".scm " #\\)) + deps) + (emit-line " # " (length deps) " dependencies") + (emit-line) + (emit-line) + )) + + (for-each (lambda (dep) + (if (not (member dep *generate-makefile-all-deps*)) + (set! *generate-makefile-all-deps* + (cons dep *generate-makefile-all-deps*)))) + deps) + + ;; for each dependency: + ;; %SCHEME% out\scheme-compiler-flat-ts.scm compat/tinyscheme.scm --outdir out\bootstrap --conspiracy --expand-only + + ;; to finish: + ;; $(SCHEME) needc-ts.scm --root out\bootstrap --flat-names --output out\sasm-flat-ts.scm sasm-ts + + (close-input-port port) + )) + +(define *generate-makefile-depth* 0) +(define *generate-makefile-all-deps* '()) +(define (generate-makefile! module-name output-port) + (if (not (module-loaded? module-name)) + (begin + (set! *generate-makefile-depth* (+ 1 *generate-makefile-depth*)) + (set! *modules* (cons module-name *modules*)) + (let ((file-name (string-append (symbol->string module-name) + ".scm"))) + (generate-makefile-file module-name file-name output-port) + (accumulate-modified! file-name)) + (set! *generate-makefile-depth* (- *generate-makefile-depth* 1)) + ) + )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (delete-if-exists! file-name) + (if (fs-exists? (read-fs file-name)) + (begin + (display ";; deleting ") + (display file-name) + (newline) + (delete-file file-name)))) + +(define (rename-temp-file! file-name-tmp file-name) + (delete-if-exists! file-name) + (display ";; renaming ") + (display file-name-tmp) + (display " to ") + (display file-name) + (newline) + (rename-file file-name-tmp file-name)) + +(define (version-check-prefix mode) + (if (eqv? mode 'generate-script) + "@echo " + (if (eqv? mode 'generate-makefile) + "# " + ";; "))) + +(define (check-output-version mode output-file) + (let* ((version-prefix (version-check-prefix mode)) + (version (string-append version-prefix *needc-version*))) + (call-with-input-file output-file + (lambda (port) + (let loop ((index 0)) + (let ((c (read-char port))) + (cond ((eof-object? c) #f) + ((and (char=? c #\newline) + (= index (string-length version))) + #t) + ((>= index (string-length version)) #f) + ((not (char=? (string-ref version index) c)) + #f) + (else (loop (+ index 1)))))))))) + +(let loop ((mode #f) + (output-file #f) + (rest-args (cdr (vector->list *argv*)))) + (cond ((null? rest-args) + #t) + ((or (string=? "--expand-only" (car rest-args)) + (string=? "--expand-syntax" (car rest-args))) + (set! *expand-mode* #t) + (display ";; enabled expand-only script mode") + (newline) + (loop mode output-file (cdr rest-args))) + ((string=? "--script-mode" (car rest-args)) + (if mode + (error "Mode already set")) + (loop 'generate-script output-file (cdr rest-args))) + ((string=? "--makefile-mode" (car rest-args)) + (if mode + (error "Mode already set")) + (loop 'generate-makefile output-file (cdr rest-args))) + ((string=? "--windows-mode" (car rest-args)) + (set! *windows-mode* #t) + (set! *dir-sep* (string #\\)) + (loop mode output-file (cdr rest-args))) + ((string=? "--root" (car rest-args)) + (if (null? (cdr rest-args)) + (error "Invalid command line, no argument to --root")) + (display ";; updating root to ") + (display (car (cdr rest-args))) + (newline) + (set! *root* (string-append (car (cdr rest-args)) "/")) + (loop mode output-file (cdr (cdr rest-args)))) + ((string=? "--flat-names" (car rest-args)) + (set! *flat-module-names* #t) + (loop mode output-file (cdr rest-args))) + ((string=? "--output" (car rest-args)) + (if (null? (cdr rest-args)) + (error "Invalid command line, no argument to --output")) + (display ";; producing output file ") + (display (car (cdr rest-args))) + (newline) + (loop mode (car (cdr rest-args)) (cdr (cdr rest-args)))) + (else + (if (not (null? (cdr rest-args))) + (error "bad command line, extra arguments")) + (let* ((output-fs (read-fs output-file)) + (tmp-output-file (if output-file + (string-append output-file ".tmp") + #f)) + (unused (if tmp-output-file + (delete-if-exists! tmp-output-file))) + (tmp-output-port (if tmp-output-file + (open-output-file tmp-output-file) + (current-output-port)))) + (define (emit . args) + (for-each (lambda (arg) (display arg tmp-output-port)) + args)) + (define (emit-line . args) + (apply emit args) + (newline tmp-output-port)) + + (if output-fs + (set! *output-fs* output-fs)) + + (if (fs-exists? *output-fs*) + (let ((match (check-output-version mode output-file))) + (if (not match) + (begin (display ";; needc version updated, modifying script") + (newline) + (set! *output-modified* #t))))) + + (if (and *expand-mode* (not mode)) + (error "bad command line, expand-mode without mode")) + + (if (eqv? 'generate-script mode) + (begin (emit-line (version-check-prefix mode) *needc-version*) + (if *windows-mode* + (emit-line "@setlocal") + ) + (set! *generate-script-main-module* (string->symbol (car rest-args))) + (generate-script! *generate-script-main-module* + tmp-output-port)) + (if (eqv? 'generate-makefile mode) + (begin (emit-line (version-check-prefix mode) *needc-version*) + (emit-line) + (generate-makefile! (string->symbol (car rest-args)) + tmp-output-port) + + (let ((main-symbol (generate-makefile-dep-symbol-name (string->symbol (car rest-args))))) + (emit-line main-symbol "=" #\\) + (for-each (lambda (dep) + (emit-line " " dep ".scm " #\\)) + (reverse *generate-makefile-all-deps*)) + (emit-line " # " (length *generate-makefile-all-deps*) " dependencies listed") + (emit-line) + )) + (load-module! (string->symbol (car rest-args)) + tmp-output-port))) + + (if tmp-output-file + (close-output-port tmp-output-port)) + + ;; (display "output exists? ") + ;; (display (fs-exists? output-file)) + ;; (newline) + + ;; (display "output-modified ") + ;; (display *output-modified*) + ;; (newline) + + (if (or (not (fs-exists? *output-fs*)) + (and tmp-output-file *output-modified*)) + (begin + (delete-if-exists! output-file) + (rename-temp-file! tmp-output-file output-file)) + (begin + (display ";; ") + (display output-file) + (display " up-to-date") + (newline)) + ) + + (if tmp-output-file + (delete-if-exists! tmp-output-file)) + + )))) diff --git a/src/parse/genparse.scm b/src/parse/genparse.scm new file mode 100644 index 0000000..0566ad4 --- /dev/null +++ b/src/parse/genparse.scm @@ -0,0 +1,508 @@ +(need util/list) + +(define (println . args) + (for-each display args) + (newline)) + +;; productions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (production-lhs production) + (car production)) + +(define (production-rhs production) + (cdr production)) + +(define (make-production-item prod item) + (cons prod item)) + +(define (production-initial-item prod) + (make-production-item prod (production-rhs prod))) + +(define (production->items prod) + (define (iter rhs-rest items) + (if (null? rhs-rest) + (reverse (cons (make-production-item prod rhs-rest) + items)) + (iter (cdr rhs-rest) + (cons (make-production-item prod rhs-rest) + items)))) + (iter (production-rhs prod) '())) + +;; items ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (item-production item) + (car item)) + +(define (item-position item) + (cdr item)) + +(define (item-first item) + (cadr item)) + +(define (item-transition item) + (make-production-item (item-production item) + (cdr (item-position item)))) + +(define (item-done? item) + (null? (item-position item))) + +(define (items-equal? item-a item-b) + (equal? item-a item-b)) + +(define (print-item item) + (define (print-rhs rhs) + (if (equal? rhs (item-position item)) + (display " .")) + (if (not (null? rhs)) + (begin (display " ") + (display (car rhs)) + (print-rhs (cdr rhs))))) + (display (production-lhs (item-production item))) + (display " ->") + (print-rhs (production-rhs (item-production item)))) + +;; grammars ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (grammar-start-production grammar) + (car grammar)) + +(define (grammar-productions grammar) + grammar) + +(define (grammar-nonterminals grammar) + (remove-duplicates equal? + (map car grammar))) + +(define (grammar-symbols grammar) + (remove-duplicates equal? + (accum append '() (grammar-productions grammar)))) + +(define (grammar-terminals grammar) + (subtract-lists equal? + (grammar-symbols grammar) + (grammar-nonterminals grammar))) + +(define (nonterminal? grammar symbol) + (member symbol (grammar-nonterminals grammar))) + +(define (productions-starting-with grammar symbol) + (filter (lambda (prod) (eqv? symbol (production-lhs prod))) + (grammar-productions grammar))) + +(define (productions-containing grammar symbol) + (filter (lambda (prod) (member symbol (production-rhs prod))) + (grammar-productions grammar))) + +(define (grammar-nullable-set grammar) + (define (find-not-nullable not-nullable symbols) + (if (null? symbols) + #f + (let ((prods (productions-starting-with grammar (car symbols)))) + (if (not (null? (filter (lambda (prod) (intersect-lists equal? + (production-rhs prod) + not-nullable)) + (productions-starting-with grammar (car symbols))))) + (car symbols) + (find-not-nullable not-nullable (cdr symbols)))))) + (define (find-nullable nullable symbols) + (if (null? symbols) + #f + (let ((prods (productions-starting-with grammar (car symbols)))) + (if (accum (lambda (a b) (and a b)) + #t + (map (lambda (prod) (list-subset? equal? (production-rhs prod) nullable )) + prods)) + (car symbols) + (find-nullable nullable (cdr symbols)))))) + (define (without l sym) + (filter (lambda (x) (not (equal? x sym))) + l)) + (define (iter not-nullable nullable to-check) + (if (null? to-check) + nullable + (let ((new-not-nullable (find-not-nullable not-nullable to-check))) + (if new-not-nullable + (iter (cons new-not-nullable not-nullable) + nullable + (without to-check new-not-nullable)) + (let ((new-nullable (find-nullable nullable to-check))) + (if new-nullable + (iter not-nullable + (cons new-nullable nullable) + (without to-check nullable)) + nullable)))))) + (iter (grammar-terminals grammar) '() (grammar-nonterminals grammar))) + +(define (grammar-first-sets grammar) + (define (add-first l sym val) + (if (null? l) + (list (cons sym val)) + (if (equal? sym (caar l)) + (cons (cons (caar l) + (union-lists equal? val (cdar l))) + (cdr l)) + (cons (car l) (add-first (cdr l) sym val))))) + (define (get-first first sym) + (let ((e (assoc sym first))) + (if e (cdr e) '()))) + (define (prod-first prod) + (car (production-rhs prod))) + (define (prod-useful? first prod) + (not (list-subset? equal? + (get-first first (prod-first prod)) + (get-first first (production-lhs prod))))) + (define (iter first all-prods) + (let loop ((prods all-prods)) + (if (null? prods) + first + (let ((prod (car prods))) + (if (and (not (null? (production-rhs prod))) + (not (null? (get-first first (prod-first prod)))) + (prod-useful? first prod)) + (iter (add-first first + (production-lhs prod) + (get-first first (prod-first prod))) + all-prods) + (loop (cdr prods))))))) + (iter (map (lambda (x) (list x x)) + (grammar-terminals grammar)) + (grammar-productions grammar))) + +(define (grammar-follow-sets grammar) + (define first-sets (cons (list '$ '$) (grammar-first-sets grammar))) + (define (get-first first sym) + (let ((e (assoc sym first))) + (if e (cdr e) '()))) + (define (add-follow l sym val) + (if (null? l) + (list (cons sym val)) + (if (equal? sym (caar l)) + (cons (cons (caar l) + (union-lists equal? val (cdar l))) + (cdr l)) + (cons (car l) (add-follow (cdr l) sym val))))) + (define (get-follow follow sym) + (let ((e (assoc sym follow))) + (if e (cdr e) '()))) + (define (iter follow all-prods) + (let loop ((prods all-prods)) + (if (null? prods) + follow + (let ((prod (car prods))) + (let prod-loop ((items (production-rhs prod))) + (cond ((null? items) + (loop (cdr prods))) + ((null? (cdr items)) + (if (and (nonterminal? grammar (car items)) + (not (null? (get-follow follow (production-lhs prod)))) + (not (list-subset? equal? + (get-follow follow (production-lhs prod)) + (get-follow follow (car items))))) + (iter (add-follow follow + (car items) + (get-follow follow (production-lhs prod))) + all-prods) + (loop (cdr prods)))) + (else + (if (and (nonterminal? grammar (car items)) + (not (null? (get-first first-sets (cadr items)))) + (not (list-subset? equal? + (get-first first-sets (cadr items)) + (get-follow follow (car items))))) + (iter (add-follow follow + (car items) + (get-first first-sets (cadr items))) + all-prods) + (prod-loop (cdr items)))))))))) + (iter (list (cons (production-lhs (grammar-start-production grammar)) + (list '$))) + (grammar-productions grammar))) + +(define (grammar-rules-filter-productions grammar-rules) + (filter (lambda (x) (not (member (car x) '(:rule :java-rule)))) + grammar-rules)) + +(define (grammar-rules-build-action-table grammar-rules) + (let ((actions (filter (lambda (x) (member (car x) '(:rule))) grammar-rules))) + (if (= (length (grammar-rules-filter-productions grammar-rules)) + (length actions)) + (cons 'vector (map (lambda (x) + (if (and (list? x) + (= 2 (length x)) + (eqv? 'lambda (car (list-ref x 1)))) + (list-ref x 1) + (error "Invalid action: " x))) + actions)) + (error "The number of productions does not equal the number of rules" + (length (grammar-rules-filter-productions grammar-rules)) + (length actions))))) + +;; LR(0) generator ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (state-from-item-list-closure grammar items) + (define (add-item item result) + (if (not (member item result)) + (cons item result) + result)) + (define (add-items items visited result) + (if (null? items) + result + (if (member (car items) visited) + (add-items (cdr items) visited result) + (add-item (car items) (add-items (cdr items) visited result))))) + (define (add-nonvisited item visited result) + (if (member item visited) + result + (cons item result))) + (define (iter items visited result) + (if (null? items) + (reverse result) + (let ((item (car items)) + (new-visited (add-item (car items) visited))) + (cond ((item-done? item) + (iter (cdr items) new-visited (add-item item result))) + ((not (nonterminal? grammar (item-first item))) + (iter (cdr items) new-visited (add-item item result))) + (else + (iter (add-items (map production-initial-item + (productions-starting-with grammar (item-first item))) + new-visited + (cdr items)) + new-visited + (add-item item result))))))) + (iter items '() '())) + +(define (state-from-item-closure grammar item) + (state-from-item-list-closure grammar (list item))) + +(define (state-items state) + state) + +(define (state-transition-symbols state) + (remove-duplicates equal? + (map item-first + (filter (lambda (i) (not (item-done? i))) + (state-items state))))) + +(define (state-transition-items state symbol) + (filter (lambda (item) + (and (not (item-done? item)) + (equal? (item-first item) symbol))) + (state-items state))) + +(define (build-lr0-state-transition-graph grammar) + (define (states-equal? state-a state-b) + (list-set=? items-equal? (state-items state-a) (state-items state-b))) + (define (build-graph queue states transitions) + (if (null? queue) + (list states transitions) + (let loop ((state (car queue)) + (state-idx (index-of (car queue) states-equal? states)) + (next-queue (cdr queue)) + (next-states states) + (next-transitions transitions) + (next-symbols (state-transition-symbols (car queue)))) + (if (null? next-symbols) + (build-graph next-queue next-states next-transitions) + (let* ((next-items (state-transition-items state + (car next-symbols))) + (next-state (state-from-item-list-closure grammar + (map item-transition next-items))) + (next-idx (index-of next-state states-equal? next-states))) + (if next-idx + (loop state + state-idx + next-queue + next-states + (append next-transitions + (list (list state-idx next-idx (car next-symbols)))) + (cdr next-symbols)) + (loop state + state-idx + (append next-queue (list next-state)) + (append next-states (list next-state)) + (append next-transitions + (list (list state-idx (length next-states) (car next-symbols)))) + (cdr next-symbols)))))))) + (let ((start-prod (grammar-start-production grammar))) + (let ((start-item (production-initial-item start-prod))) + (let ((start-state (state-from-item-closure grammar start-item))) + (build-graph (list start-state) + (list start-state) + '()))))) + +(define (lr0-graph-states graph) + (car graph)) + +(define (lr0-graph-transitions graph) + (cadr graph)) + +(define (grammar-make-table n-rows n-columns) + (let ((rows (make-vector n-rows))) + (let loop ((row 0)) + (if (< row n-rows) + (begin (vector-set! rows row (make-vector n-columns #f)) + (loop (+ row 1))) + rows)))) + +(define (grammar-table-set! tab row col val) + (vector-set! (vector-ref tab row) + col val)) + +(define (grammar-table-get tab row col) + (vector-ref (vector-ref tab row) + col)) + +(define (generate-lr0-goto-table grammar graph) + (let ((states (lr0-graph-states graph)) + (nonterm (grammar-nonterminals grammar))) + (let ((sr-table (grammar-make-table (length states) (length nonterm)))) + (for-each (lambda (tx) + (let ((sym (list-ref tx 2)) + (orig-state (list-ref tx 0)) + (next-state (list-ref tx 1))) + (if (and (member sym nonterm) + (grammar-table-get sr-table orig-state (index-of sym equal? nonterm))) + (error "Goto conflict " orig-state " " next-state " " sym)) + (if (member sym nonterm) + (grammar-table-set! sr-table + orig-state + (index-of sym equal? nonterm) + (cons 'g next-state))))) + (lr0-graph-transitions graph)) + sr-table))) + +(define (generate-lr0-table grammar graph grammar-rules) + (let ((n-states (length (lr0-graph-states graph))) + (term (append (grammar-terminals grammar) (list '$))) + (nonterm (grammar-nonterminals grammar)) + (follow-sets (grammar-follow-sets grammar))) + (define (reduce-reduce-error state-idx orig-rule-idx new-rule-idx) + (error "Reduce-reduce conflict in state " state-idx + " between rule " orig-rule-idx " and " new-rule-idx)) + (define (term? sym) (member sym term)) + (define (term-idx sym) (index-of sym equal? term)) + (define (accept-item? item) + (and (equal? (grammar-start-production grammar) + (item-production item)) + (item-done? item))) + (define (accept-state? state) + (accum (lambda (a b) (or a b)) + #f + (map accept-item? (state-items state)))) + (let ((sr-table (grammar-make-table n-states (length term)))) + (define (get-conflicts row reduce-on) + (let loop ((row (vector->list (vector-ref sr-table row))) + (terms term) + (res '())) + (if (null? row) + (filter (lambda (x) (not (equal? '$ (car x)))) + (reverse res)) + (loop (cdr row) + (cdr terms) + (if (pair? (car row)) + (if (or (null? reduce-on) + (member (car terms) reduce-on)) + (cons (cons (car terms) (cdar row)) res) + res) + res))))) + (for-each (lambda (tx) + (if (term? (list-ref tx 2)) + (grammar-table-set! sr-table + (car tx) + (term-idx (list-ref tx 2)) + (cons 's (cadr tx))))) + (lr0-graph-transitions graph)) + (for-each-idx (lambda (state idx) + (if (accept-state? state) + (grammar-table-set! sr-table + idx + (term-idx '$) + (cons 'a #f)))) + (lr0-graph-states graph)) + (let loop ((states (lr0-graph-states graph)) + (state-idx 0)) + (if (< state-idx n-states) + (begin + (for-each (lambda (item) + (if (item-done? item) + (let ((conflicts (get-conflicts + state-idx + (let ((e (assoc (production-lhs (item-production item)) + follow-sets))) + (if e (cdr e) '()))))) + (if (not (null? conflicts)) + + ;; Conflicts exist, bail out + (begin + (println "In state " state-idx "; rule " (item-production item) + " conflicts with shift states:") + (for-each (lambda (x) (println " " x)) conflicts)) + + ;; No conflicts + (let ((follow (assoc (production-lhs (item-production item)) + follow-sets))) + (if (not follow) + (error "No follow set for production " (item-production item) + " in state " state-idx)) + (for-each (lambda (term) + (let ((rule-idx (index-of (item-production item) + equal? + (grammar-productions grammar))) + (existing (grammar-table-get sr-table state-idx (term-idx term)))) + (cond ((and existing + (eqv? 'a (car existing))) + #t) + (existing + (reduce-reduce-error state-idx (cdr existing) rule-idx)) + (else + (grammar-table-set! sr-table + state-idx + (term-idx term) + (cons 'r rule-idx)))))) + (cdr follow))))))) + + (state-items (car states))) + (loop (cdr states) (+ state-idx 1))))) + sr-table))) + +(define (print-state state prefix) + (for-each (lambda (item) + (display prefix) + (print-item item) + (newline)) + (state-items state))) + +(define (print-state-transition-graph graph) + (define (justify str width suffix) + (if (< (string-length str) width) + (justify (string-append str suffix) width suffix) + str)) + (let loop ((states (list-ref graph 0)) + (count 0) + (transitions (list-ref graph 1))) + (if (not (null? states)) + (begin + (display (justify (string-append "+- State " (number->string count) " -") 50 "-")) + (newline) + (print-state (car states) "| ") + (display (justify "+-" 50 "-")) + (newline) + (newline) + (let loop ((t transitions) + (found #f)) + (if (not (null? t)) + (if (equal? count (car (car t))) + (let ((tx (car t))) + (display "State ") + (display (car tx)) + (display " -> State ") + (display (cadr tx)) + (display " on ") + (display (caddr tx)) + (newline) + (loop (cdr t) #t)) + (loop (cdr t) found)) + (if found (newline)))) + (loop (cdr states) (+ count 1) transitions))))) + diff --git a/src/parse/parse.scm b/src/parse/parse.scm new file mode 100644 index 0000000..5c8f86e --- /dev/null +++ b/src/parse/parse.scm @@ -0,0 +1,104 @@ +(define (token-value tok) + (car tok)) + +(define (token-line tok) + (list-ref tok 1)) + +(define (token-column tok) + (list-ref tok 2)) + +(define (token-line-col tok) + (cdr tok)) + +(define (run-parse grammar terminals nonterminals sr-table goto-table action-table tokens) + + ;; @hack duplicated code here, to eliminate deps + (define (grammar-productions grammar) + grammar) + (define (production-lhs prod) + (car prod)) + (define (production-rhs prod) + (cdr prod)) + + (define (index-of obj list) + (- (length list) (length (member obj list)))) + (define (table-ref-idx i j) + (vector-ref (vector-ref sr-table i) j)) + (define (table-ref i j) + (if (symbol? j) + (table-ref-idx i (index-of j terminals)) + (table-ref-idx i j))) + (define (goto-ref-idx i j) + (vector-ref (vector-ref goto-table i) j)) + (define (goto-ref i j) + (if (symbol? j) + (goto-ref-idx i (index-of j nonterminals)) + (goto-ref-idx i j))) + (define (get-rule idx) + (list-ref (grammar-productions grammar) idx)) + (define (shift-stack cur-stack token cur-state value) + (cons (list token cur-state value) + cur-stack)) + (define (reduce-stack stack rule action) + (let loop ((s stack) + (args '()) + (n (length (production-rhs rule)))) + (if (zero? n) + (list s (apply action args)) + (loop (cdr s) (cons (list-ref (car s) 2) args) (- n 1))))) + (define (get-top-state reduced) + (list-ref (car (get-reduced-stack reduced)) 1)) + (define (get-reduced-stack reduced) + (list-ref reduced 0)) + (define (get-reduced-value reduced) + (list-ref reduced 1)) + (define (parser-reject input . msg) + (if (not (null? input)) + (let ((next (car input))) + (for-each (lambda (x) (display x (current-error-port))) + (list "Parse error '" + (list-ref next 1) + "', line " + (+ (list-ref next 2) 1) + " column " + (+ (list-ref next 3) 1)))) + (for-each (lambda (x) (display x (current-error-port))) + (list "Parse error at end-of-file"))) + (newline (current-error-port)) + #f) + (define (parser-accept stack) + (list-ref (car stack) 2)) + (define (iter cur-state stack input) + (cond + ((null? input) + (parser-reject input "No more tokens are available in the input, but the parser didn't reach an accept state.")) + ((not (member (caar input) terminals)) + (parser-reject input "There was an unrecognized token in the input: " (car input))) + ((not (table-ref cur-state (caar input))) + (parser-reject input "Syntax error; the following token is unexpected: " (car input))) + (else + (let ((op (table-ref cur-state (caar input)))) + (case (car op) + ((s) (iter (cdr op) + (shift-stack stack (car input) (cdr op) (cdar input)) + (cdr input))) + ((r) (let* ((rule (get-rule (cdr op))) + (action (vector-ref action-table (cdr op))) + (reduced (reduce-stack stack rule action)) + (top-state (get-top-state reduced)) + (next-state (if (goto-ref top-state (production-lhs rule)) + (cdr (goto-ref top-state (production-lhs rule))) + (error "NO GOTO STATE " rule reduced top-state)))) + (iter next-state + (shift-stack (get-reduced-stack reduced) + (production-lhs rule) + next-state + (get-reduced-value reduced)) + input))) + ((a) (if (and (eqv? '$ (caar input)) + (null? (cdr input))) + (parser-accept stack) + (parser-reject input "The input reached an accept state but was not fully consumed."))) + (else (error "MALFORMED SR-TABLE"))))))) + (iter 0 (shift-stack '() '*non-token* 0 '*invalid-value*) tokens)) + diff --git a/src/parser.scm b/src/parser.scm new file mode 100644 index 0000000..fb46d14 --- /dev/null +++ b/src/parser.scm @@ -0,0 +1,11 @@ +(need parse/parse) +(load "ast.scm") +(load "pretty.scm") +(load "minijava-lexer.scm") +(load "minijava-parser.scm") + +(let ((parse (minijava-parse-input (call-with-input-file (vector-ref *argv* 1) minijava-lexically-analyze)))) + (and parse + (display "ok, parsed file") + (newline) + (accept-visitor parse pretty-print-ast 0))) diff --git a/src/pat/pat.scm b/src/pat/pat.scm new file mode 100644 index 0000000..3bdbb0d --- /dev/null +++ b/src/pat/pat.scm @@ -0,0 +1,185 @@ +;; pat.scm +;; +;; Some simple s-exp pattern matching and rewriting routines. + +(define (pattern-match pattern obj) + (define (terminal? pat) + (or (null? pat) + (number? pat) + (boolean? pat) + (symbol? pat))) + (define (combine-result a b) + (and a b (append a b))) + (define (test-list results) + (define (iter current-result remaining-results) + (if (null? remaining-results) + current-result + (iter (and current-result + (car remaining-results)) + (cdr remaining-results)))) + (iter #t results)) + + (define (accumulate-environment env obj sym) + ;; + ;; Checks to see if the given symbol is already defined in the + ;; environment, and if so, validates that it is already defined to + ;; an equal object. If not, it is added to the environment. + ;; + (let ((entry (assoc sym env))) + (cond ((not entry) + (cons (cons sym obj) + env)) + ((equal? (cdr entry) obj) + env) + (else + #f)))) + (define (match-in-env env pat obj) + (cond ((terminal? pat) + (if (equal? pat obj) + env + #f)) + + ;; + ;; (? ) + ;; + ;; Matches anything. + ;; + ((and (pair? pat) + (eqv? '? (car pat))) + (and (pair? (cdr pat)) + (null? (cddr pat)) + (symbol? (cadr pat)) + (accumulate-environment env obj (cadr pat)))) + + ;; + ;; ( ) + ;; + ;; Matches any object that matches the specified predicate. + ;; + ((and (pair? pat) + (procedure? (car pat))) + (and (pair? (cdr pat)) + (null? (cddr pat)) + (symbol? (cadr pat)) + ((car pat) obj) + (accumulate-environment env obj (cadr pat)))) + + ;; + ;; (?? ) + ;; + ;; Matches an object that matches the specified + ;; . To build the result, the return + ;; value of applied to that object is + ;; used. + ;; + ((and (pair? pat) + (eqv? '?? (car pat)) + (pair? (cdr pat)) + (procedure? (cadr pat)) + (pair? (cddr pat)) + (symbol? (caddr pat)) + (null? (cdddr pat))) + (let ((sym (caddr pat)) + (predicate (cadr pat))) + (let ((transformed-obj (predicate obj))) + (and transformed-obj + (accumulate-environment env transformed-obj sym))))) + + ;; + ;; (@ ) + ;; + ;; Matches a list of elements where each element matches + ;; . + ;; + ((and (pair? pat) + (eqv? '@ (car pat)) + (pair? (cdr pat)) + (procedure? (cadr pat)) + (pair? (cddr pat)) + (symbol? (caddr pat)) + (null? (cdddr pat))) + (let ((sym (caddr pat)) + (predicate (cadr pat))) + (and (list? obj) + (test-list (map predicate obj)) + (accumulate-environment env obj sym)))) + + ;; + ;; (@ ) + ;; + ;; Matches a list of elements where each element matches + ;; . To build the result, is invoked + ;; on each element of the list. + ;; + ((and (pair? pat) + (eqv? '@ (car pat)) + (pair? (cdr pat)) + (procedure? (cadr pat)) + (pair? (cddr pat)) + (procedure? (caddr pat)) + (pair? (cdddr pat)) + (symbol? (cadddr pat)) + (null? (cddddr pat))) + (let ((sym (cadddr pat)) + (predicate (cadr pat)) + (transform (caddr pat))) + (and (list? obj) + (test-list (map predicate obj)) + (accumulate-environment env (map transform obj) sym)))) + + ;; + ;; (@@ ) + ;; + ;; Matches a list of elements where each element matches + ;; . To build the result list, the + ;; return value of applied to that + ;; element is used. + ;; + ((and (pair? pat) + (eqv? '@@ (car pat)) + (pair? (cdr pat)) + (procedure? (cadr pat)) + (pair? (cddr pat)) + (symbol? (caddr pat)) + (null? (cdddr pat))) + (let ((sym (caddr pat)) + (predicate-transform (cadr pat))) + (and (list? obj) + (let ((transformed-obj (map predicate-transform obj))) + (and (test-list transformed-obj) + (accumulate-environment env transformed-obj sym)))))) + + ;; + ;; Recursive case - invoke recursively on the car and cdr + ;; + ((pair? pat) + (and (pair? obj) + (let ((new-env (match-in-env env (car pat) (car obj)))) + (and new-env + (match-in-env new-env (cdr pat) (cdr obj)))))) + (else (error "Invalid pattern -- " pat)))) + (match-in-env '() pattern obj)) + +(define (pattern-match-replace pattern spec) + (define (terminal? pat) + (or (null? pat) + (number? pat) + (boolean? pat) + (symbol? pat))) + (define (combine-res a b) + (and a b (append a b))) + (define (replace-in-env obj) + (cond ((terminal? obj) + obj) + ((and (pair? obj) + (or (eqv? '? (car obj)) + (procedure? (car obj)))) + (let ((entry (assoc (cadr obj) spec))) + (if entry + (cdr entry) + (error "Bad match spec for pattern -- pattern-match-replace")))) + ((pair? obj) + (cons (replace-in-env (car obj)) + (replace-in-env (cdr obj)))) + (else (error "Bad pattern -- pattern-match-replace")))) + (replace-in-env pattern)) diff --git a/src/pretty.scm b/src/pretty.scm new file mode 100644 index 0000000..d275756 --- /dev/null +++ b/src/pretty.scm @@ -0,0 +1,203 @@ +(define (pretty-print-ast type node indent) + (define (print indent? . args) + (if indent? + (let loop ((i 0)) + (if (< i indent) + (begin (display " ") (loop (+ i 1)))))) + (if (not (list? args)) + (error "Unable to print args - not a proper list")) + (for-each (lambda (x) (cond ((symbol? x) + (display (ast-node-attr node x))) + ((and (list? x) (= 2 (length x)) (eqv? '@ (car x))) + (accept-visitor (ast-node-attr node (cadr x)) pretty-print-ast 0)) + (else (display x)))) + args)) + (define (println indent? . args) + (apply print indent? args) + (newline) + (display ";")) + (define (: attr) + (ast-node-attr node attr)) + (define (print-arglist list) + (print #f "(") + (if (not (null? list)) + (begin (print #f " ") + (accept-visitor (car list) pretty-print-ast 0) + (if (not (list? list)) + (error "Unable to print arglist - not a proper list")) + (for-each (lambda (child) + (print #f ", ") + (accept-visitor child pretty-print-ast 0)) + (cdr list)) + (print #f " "))) + (print #f ")")) + (case type + ((program) + (display ";") + (visit-each pretty-print-ast + (: ':class-list) + 0) + (newline)) + ((class) + (print #t "class " ':class-name) + (if (: ':parent) + (println #f " extends " ':parent) + (println #f)) + (println #t "{") + (visit-each pretty-print-ast + (: ':instance-vars) + (+ indent 2)) + (if (not (null? (: ':instance-vars))) + (println #f)) + (visit-each pretty-print-ast + (: ':static-vars) + (+ indent 2)) + (if (not (null? (: ':static-vars))) + (println #f)) + (visit-each pretty-print-ast + (: ':constructors) + (+ indent 2)) + (visit-each pretty-print-ast + (: ':methods) + (+ indent 2)) + (visit-each pretty-print-ast + (: ':static-methods) + (+ indent 2)) + (println #t "}") + (println #f)) + + ((var) + (println #t '(@ :type) " " ':name ";")) + ((static-var) + (println #t "static " '(@ :type) " " ':name ";")) + ((method) + (print #t "public " + (if (: ':static?) "static " "") + '(@ :return-type) " " ':name "") + (print-arglist (: ':param-list)) + (println #f "") + (println #t "{") + (visit-each pretty-print-ast + (: ':local-vars) + (+ indent 2)) + (if (not (null? (: ':local-vars))) + (println #f "")) + (visit-each pretty-print-ast + (: ':statements) + (+ indent 2)) + (println #t "}") + (println #f)) + + ((constructor) + (print #t "public " '(@ :return-type)) + (print-arglist (: ':param-list)) + (println #f "") + (println #t "{") + (visit-each pretty-print-ast + (: ':local-vars) + (+ indent 2)) + (if (not (null? (: ':local-vars))) + (println #f "")) + (visit-each pretty-print-ast + (: ':statements) + (+ indent 2)) + (println #t "}") + (println #f)) + + ((compound-statement) + (println #t "{") + (visit-each pretty-print-ast + (: ':statements) + (+ indent 2)) + (println #t "}")) + + ((return-statement) + (println #t "return " '(@ :exp) ";")) + + ((if-statement) + (println #t "if( " '(@ :condition) " )") + (accept-visitor (: ':consequent) pretty-print-ast (+ indent 2)) + (println #t "else") + (accept-visitor (: ':antecedent) pretty-print-ast (+ indent 2))) + + ((while-statement) + (println #t "while( " '(@ :condition) " )") + (accept-visitor (: ':body) pretty-print-ast (+ indent 2))) + + ((print-statement) + (println #t "System.out.println( " '(@ :exp) " );")) + + ((assignment-statement) + (print #t ':ident " = ") + (accept-visitor (: ':exp) pretty-print-ast 0) + (println #f ";")) + + ((array-assignment-statement) + (print #t ':ident "[ ") + (accept-visitor (: ':index-exp) pretty-print-ast 0) + (print #f " ] = ") + (accept-visitor (: ':value-exp) pretty-print-ast 0) + (println #f ";")) + + ((simple-type) + (print #f ':name)) + + ((array-type) + (print #f '(@ :element-type) "[]")) + + ((user-type) + (print #f ':name)) + + ((param) + (print #f '(@ :type) " " ':name)) + + ((and-expression less-than-expression add-expression subtract-expression multiply-expression + equal-to-expression) + (print #t + "( " + '(@ :left) + " " + (case type + ((and-expression) "&&") + ((less-than-expression) "<") + ((add-expression) "+") + ((subtract-expression) "-") + ((multiply-expression) "*") + ((equal-to-expression) "==") + (else (error "Invalid binary expression type " type))) + " " + '(@ :right) + " )")) + + ((not-expression) + (print #f "!( " '(@ :exp) " )")) + + ((array-ref-expression) + (print #f '(@ :array-exp) "[ " '(@ :index-exp) " ]")) + + ((length-expression) + (print #f '(@ :exp) ".length")) + + ((method-call-expression) + (print #f '(@ :object) "." ':method-name "") + (print-arglist (: ':arg-list)) + (print #f (if (tailcall? node) " /* tailcall */" ""))) + + ((boolean-constant-expression number-constant-expression char-constant-expression string-constant-expression) + (print #f ':value)) + + ((variable-expression) + (print #f ':ident)) + + ((this-expression) + (print #f "this")) + + ((new-array-expression) + (print #f "new " '(@ :element-type) "[ " '(@ :length) " ]")) + + ((new-object-expression) + (print #f "new " ':class-name "") + (print-arglist (: ':arg-list))) + + (else + (error "Pretty-Print: Unknown AST node type " type node)))) diff --git a/src/read-expanded-format.scm b/src/read-expanded-format.scm new file mode 100644 index 0000000..9f8ba8c --- /dev/null +++ b/src/read-expanded-format.scm @@ -0,0 +1,61 @@ +;;; scheme-compiler version 04-21-2018 0.1 +;;; expanded from scheme-main + +(define read2 + (lambda (bound_00000002@port) + (letrec ((bound_00000055@read-string (lambda (bound_00000086@res) + (display "read-string") + (newline) + ((lambda (bound_00000088@char) + (if (eof-object? bound_00000088@char) + (list->string (reverse bound_00000086@res)) + (if (char=? #\\ bound_00000088@char) + (bound_00000055@read-string (cons (read-char bound_00000002@port) + bound_00000086@res)) + (if (char=? #\" bound_00000088@char) + (list->string (reverse bound_00000086@res)) + (bound_00000055@read-string (cons bound_00000088@char bound_00000086@res)))))) + (read-char bound_00000002@port)))) + (bound_00000031@read-list (lambda (bound_00000069@l) + (display "read-list") + (newline) + (bound_00000018@eat-whitespace) + (if (eof-object? (begin (display "before rl-peek-char") + (newline) + ((lambda (bound_00000078@r) + (display "1after peek-char-") + (newline) + (display bound_00000078@r) + (newline) bound_00000078@r) + (peek-char bound_00000002@port)))) + (error "Input was terminated while looking for a closing parens.") + (if ((lambda (bound_00000079@r2) (display "r2") (newline) (display bound_00000079@r2) (newline) bound_00000079@r2) (char=? (begin (display "2nd peek-char") (newline) ((lambda (bound_00000081@r) (display "2ndafter peek-char============") (newline) (display bound_00000081@r) (newline) bound_00000081@r) (peek-char bound_00000002@port))) #\))) + (begin (display "read close paren") (newline) (read-char bound_00000002@port) (reverse bound_00000069@l)) + (begin (display "read-list else") (newline) ((lambda (bound_00000084@elem) + (if (if (symbol? bound_00000084@elem) + (string=? "." (symbol->string bound_00000084@elem)) + #f) + ((lambda (bound_00000085@ans) + (bound_00000018@eat-whitespace) + (bound_00000007@eat #\)) bound_00000085@ans) (bound_00000024@fix-improper bound_00000069@l (read2 bound_00000002@port))) (bound_00000031@read-list (cons bound_00000084@elem bound_00000069@l)))) (read2 bound_00000002@port))))))) + (bound_00000024@fix-improper (lambda (bound_00000067@head bound_00000068@tail) (display "fix-improper") (newline) (if (null? bound_00000067@head) bound_00000068@tail (bound_00000024@fix-improper (cdr bound_00000067@head) (cons (car bound_00000067@head) bound_00000068@tail))))) + (bound_00000018@eat-whitespace (lambda () (display "eat-whitespace") (display bound_00000002@port) (newline) (if (begin (display "before char-whitespace ") (newline) ((lambda (bound_00000066@v) (display "after char-whitespace ") (newline) (display bound_00000066@v) (newline) bound_00000066@v) (char-whitespace? (peek-char bound_00000002@port)))) (begin (display "before read-char ") (newline) (read-char bound_00000002@port) (display "after read-char") (newline) (bound_00000018@eat-whitespace)) '()))) + (bound_00000007@eat (lambda (bound_00000061@char) (display "eat") (newline) (if ((lambda (bound_00000063@res) (if bound_00000063@res bound_00000063@res (member (read-char bound_00000002@port) bound_00000061@char))) (if (char? bound_00000061@char) (char=? bound_00000061@char (read-char bound_00000002@port)) #f)) #t (error "Expecting other character -- READ" bound_00000002@port bound_00000061@char)))) + (bound_00000003@standard-delimiters (list->string (list #\space #\( #\) #\newline #\" #\; #\" (integer->char 13) (integer->char 9))))) + (display "read2 let*") + (newline) + ((lambda (bound_00000089@char) + ((lambda (bound_00000090@next) + ((lambda () (if (eof-object? bound_00000089@char) bound_00000089@char (if (char=? #\" bound_00000089@char) (bound_00000055@read-string '()) (if (char=? #\( bound_00000089@char) (bound_00000031@read-list '()) bound_00000089@char)))))) + (if (eof-object? bound_00000089@char) + bound_00000089@char + (peek-char bound_00000002@port)))) + (read-char bound_00000002@port))))) + +(define f (open-input-file "tests/read-dat.scm")) +(display f) +(newline) +(define c (read2 f)) +(display c) +(newline) +(close-input-port f) diff --git a/src/regex/compile.scm b/src/regex/compile.scm new file mode 100644 index 0000000..45f274c --- /dev/null +++ b/src/regex/compile.scm @@ -0,0 +1,181 @@ +(need regex/nfa) +(need regex/dfa) +(need util/list) +(need util/format) + +(define unique-state + (let ((n 0)) + (lambda () + (set! n (+ n 1)) + n))) + +(define :emit-nothing '()) + +(define (compile-char char) + (let ((start (unique-state)) + (end (unique-state))) + (build-nfa start + (list end) + (list (nfa-rule start char end)) + :emit-nothing))) + +(define (compile-optional-string stuff) + (compile-char (list-ref stuff 1))) + +(define (nfas-independent? list-of-nfas) + (null? (accum-implicit (list-intersecter state=?) + (map nfa.referenced-states list-of-nfas)))) + +(define (compile-emit-rules-for-new-end end an-nfa) + (let ((emitted (nfa.get-emitted-values-for-states + an-nfa + (nfa.final-states an-nfa)))) + (if (not (null? emitted)) + (list (cons end emitted)) + '()))) + +(define (compile-optional an-nfa) + (let ((start (unique-state)) + (end (unique-state))) + (build-nfa start + (list end) + (append + (list (nfa-lambda-rule start end) + (nfa-lambda-rule start (nfa.initial-state an-nfa))) + (map (lambda (final) + (nfa-lambda-rule final end)) + (nfa.final-states an-nfa)) + (nfa.rule-set an-nfa)) + (append (nfa.emit-rule-set an-nfa) + (compile-emit-rules-for-new-end end an-nfa))))) + +(define (compile-or list-of-nfas) + (cond ((null? list-of-nfas) + (error "Need at least one NFA -- COMPILE-OR")) + ((= 1 (length list-of-nfas)) + (car list-of-nfas)) + (else + (if (not (nfas-independent? list-of-nfas)) + (error "List of nfas have overlapping rules and/or states -- COMPILE-OR")) + (let ((start (unique-state))) + (build-nfa start + (append-map nfa.final-states list-of-nfas) + (append + (map (lambda (an-nfa) + (nfa-lambda-rule start + (nfa.initial-state an-nfa))) + list-of-nfas) + (append-map nfa.rule-set list-of-nfas)) + (append-map nfa.emit-rule-set list-of-nfas)))))) + +(define (compile-emit accept-nfa value-to-emit emit-priority) +;; Build an NFA equivalent to accept-nfa except that all accept states +;; will emit value value-to-emit. + (build-nfa (nfa.initial-state accept-nfa) + (nfa.final-states accept-nfa) + (nfa.rule-set accept-nfa) + ; append the rules to emit the value to each accept state. + (append (nfa.emit-rule-set accept-nfa) + (map (lambda (x) (cons x (cons value-to-emit emit-priority))) + (nfa.final-states accept-nfa))))) + +(define (compile-append list-of-nfas) + (define (append-nfas nfa-a nfa-b) + (if (not (null? (nfa.emit-rule-set nfa-a))) + (error "emit rules ignored for NFA in compile-append" + (nfa.emit-rule-set nfa-a))) + (build-nfa (nfa.initial-state nfa-a) + (nfa.final-states nfa-b) + (append (map (lambda (end) + (nfa-lambda-rule end (nfa.initial-state nfa-b))) + (nfa.final-states nfa-a)) + (nfa.rule-set nfa-a) + (nfa.rule-set nfa-b)) + (append (nfa.emit-rule-set nfa-a) + (nfa.emit-rule-set nfa-b)))) + (define (iter list-of-nfas) + (cond ((null? list-of-nfas) + (error "Unable to compile null list of NFAs -- COMPILE-APPEND")) + ((null? (cdr list-of-nfas)) + (car list-of-nfas)) + (else (append-nfas (car list-of-nfas) + (iter (cdr list-of-nfas)))))) + (if (and (> (length list-of-nfas) 1) + (not (nfas-independent? list-of-nfas))) + (error "Unable to compile non-independent NFAs -- COMPILE-APPEND")) + (iter list-of-nfas)) + +(define (compile-* an-nfa) + (let ((start (unique-state)) + (end (unique-state))) + (build-nfa start + (list start end) + (cons (nfa-lambda-rule start (nfa.initial-state an-nfa)) + (append (list (nfa-lambda-rule end start)) + (map (lambda (orig-end) + (nfa-lambda-rule orig-end end)) + (nfa.final-states an-nfa)) + (nfa.rule-set an-nfa))) + (append (nfa.emit-rule-set an-nfa) + (compile-emit-rules-for-new-end end an-nfa))))) + +(define (uniqueify-nfa an-nfa) + (define (state-renamer) + (let ((names '())) + (lambda (name) + (let ((rename (assoc name names))) + (if rename + (cdr rename) + (let ((rename (unique-state))) + (set! names (cons (cons name rename) + names)) + rename)))))) + (define (uniqueify-rule rule renamer) + (cond ((nfa-rule.lambda? rule) (nfa-lambda-rule (renamer (nfa-rule.from rule)) + (renamer (nfa-rule.to rule)))) + (else (nfa-rule (renamer (nfa-rule.from rule)) + (nfa-rule.value rule) + (renamer (nfa-rule.to rule)))))) + (let ((rename (state-renamer))) + (build-nfa (rename (nfa.initial-state an-nfa)) + (map rename (nfa.final-states an-nfa)) + (map (lambda (rule) (uniqueify-rule rule rename)) + (nfa.rule-set an-nfa)) + (map (lambda (rule) (cons (rename (car rule)) + (cdr rule))) + (nfa.emit-rule-set an-nfa))))) + +(define (compile-+ an-nfa) + (compile-append (list (uniqueify-nfa an-nfa) (compile-* an-nfa)))) + +(define (compile-string s) + (if (not (string? s)) + (error "Unable to compile object -- COMPILE-STRING" s)) + (compile-append (map compile-char (string->list s)))) + +(define (println string . args) + (display (apply format (cons string args))) + (newline)) + +(define (display-nfa an-nfa) + (println "Start: ~" (nfa.initial-state an-nfa)) + (println "End: ~" (nfa.final-states an-nfa)) + (for-each (lambda (rule) + (if (nfa-rule.lambda? rule) + (println "Lambda: ~ ~" (nfa-rule.from rule) (nfa-rule.to rule)) + (println "Value: ~ ~ ~" (nfa-rule.from rule) (nfa-rule.to rule) + (nfa-rule.value rule)))) + (nfa.rule-set an-nfa))) + +(define (test-nfa n string) + (nfa.reset! n) + (for-each (lambda (char) + (write + (list 'char: char + 'states: (nfa.input! n char) + 'failed?: (nfa.failed? n) + 'done?: (nfa.done? n))) + (newline)) + (string->list string)) + (display "NFA Accepts? ") (display (nfa.done? n)) + (newline)) diff --git a/src/regex/dfa.scm b/src/regex/dfa.scm new file mode 100644 index 0000000..1d6dd37 --- /dev/null +++ b/src/regex/dfa.scm @@ -0,0 +1,266 @@ +(need util/list) +(need util/string) +(need util/vector) +(need regex/fsm) +(need regex/fast-dfa) +(need algo/bsearch) +(need algo/quicksort) + +;; DFA states ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define state=? equal?) + +(define (state-in? state state-list) + (list-contains? state=? state state-list)) + +(define (remove-duplicate-states l) + (remove-duplicates state=? l)) + +;; DFA rules ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (rule from value to) + (vector from value to)) +(define (rule.next r) + (vector-ref r 2)) +(define (rule.from r) + (vector-ref r 0)) +(define (rule.starts-from? r s) + (state=? (rule.from r) s)) +(define (rule.value r) + (vector-ref r 1)) +(define (rule.value? r val) + (or (equal? (rule.value r) val) + (and (string? (rule.value r)) + (char? val) + (strchr (rule.value r) val)))) + +(define (get-rule rules from val) + (define (iter rules) + (cond ((null? rules) #f) + ((and (state=? from (rule.from (car rules))) + (rule.value? (car rules) val)) + (car rules)) + (else (iter (cdr rules))))) + (iter rules)) + +(define (get-next-state rules cur x) + (let ((rule (get-rule rules cur x))) + (if rule + (rule.next rule) + #f))) + +;; DFA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (dfa? obj) + (tagged? 'dfa obj)) + +(define (dfa.current dfa) + ((safe-contents 'dfa dfa) 'current)) +(define (dfa.initial-state dfa) + ((safe-contents 'dfa dfa) 'start)) +(define (dfa.end-states dfa) + ((safe-contents 'dfa dfa) 'enders)) +(define (dfa.done? dfa) + ((safe-contents 'dfa dfa) 'done?)) +(define (dfa.input! dfa obj) + ((safe-contents 'dfa dfa) 'go! obj)) +(define (dfa.reset! dfa) + ((safe-contents 'dfa dfa) 'reset!)) +(define (dfa.failed? dfa) + ((safe-contents 'dfa dfa) 'failed?)) +(define (dfa.rule-set dfa) + ((safe-contents 'dfa dfa) 'rule-set)) +(define (dfa.emit-rule-set dfa) + ((safe-contents 'dfa dfa) 'emit-rule-set)) +(define (dfa.get-emitted-value-for-state dfa state) + (assoc state (dfa.emit-rule-set dfa))) +(define (dfa.current-emitted-value dfa) + (dfa.get-emitted-value-for-state dfa (dfa.current dfa))) +(define (dfa.reachable-states dfa) + (depth-first-search state=? (dfa.initial-state dfa) + (lambda (state) + (map rule.next (filter (lambda (r) + (rule.starts-from? r state)) + (dfa.rule-set dfa)))))) + +(define (dfa.referenced-states dfa) + (remove-duplicates state=? + `(,(dfa.initial-state dfa) + ,@(dfa.end-states dfa) + ,@(map rule.from (dfa.rule-set dfa)) + ,@(map rule.next (dfa.rule-set dfa))))) + + + +(define (build-dfa start end rules emit-rules) + (let* ((cur start) + (failed #f)) + (define (get-start) + start) + (define (get-enders) + end) + (define (rule-set) + rules) + (define (emit-rule-set) + emit-rules) + (define (reset!) + (set! cur start) + (set! failed #f)) + (define (current) + (if (not failed) + cur + (set! failed #t))) + (define (go! x) + (if (not failed) + (let ((next (get-next-state rules cur x))) + (if (not next) + (set! failed #t) + (begin (set! cur next) next))) + (set! failed #t))) + (define (done?) + (and (not failed) (state-in? cur end))) + (define (failed?) failed) + (define (dfa-dispatch sym . args) + (apply (case sym + ((current) current) + ((start) get-start) + ((enders) get-enders) + ((go!) go!) + ((rule-set) rule-set) + ((emit-rule-set) emit-rule-set) + ((failed?) failed?) + ((done?) done?) + ((reset!) reset!)) + args)) + (if (not (list? end)) + (error "End must be a list of states -- DFA" start end rules)) + (if (not (list? rules)) + (error "Rules must be a list of rules -- DFA" start end rules)) + (tag 'dfa dfa-dispatch))) + +;; DFA transform routines ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (dfa-serialize dfa) + `(build-dfa (quote ,(dfa.initial-state dfa)) + (quote ,(dfa.end-states dfa)) + (quote ,(dfa.rule-set dfa)) + (quote ,(dfa.emit-rule-set dfa)))) + +(define (dfa-transform d transform) + (build-dfa (transform (dfa.initial-state d)) + (map transform (dfa.end-states d)) + (map (lambda (r) + (rule (transform (rule.from r)) + (rule.value r) + (transform (rule.next r)))) + (dfa.rule-set d)) + (map (lambda (r) + (cons (transform (car r)) + (cdr r))) + (dfa.emit-rule-set d)))) + +(define (dfa-rename d state-a state-b) + (define (replace x) + (if (state=? state-a x) state-b x)) + (dfa-transform d replace)) + +;; (define +;; ex (build-dfa #\a (list #\b) +;; (list (rule #\a 0 #\b) +;; (rule #\a 2 #\b) +;; (rule #\b 1 #\a) +;; (rule #\c 1 #\b) +;; (rule #\c 3 #\a) +;; (rule #\z 5 #\b) +;; (rule #\c 2 #\b)) +;; '())) + +;; DFA graphviz integration ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (dfa.graphviz dfa) + (display "digraph deterministic_finite_automaton {\n") + (display " rankdir=LR;\n") + (begin (display " node [shape = doublecircle]; ") + (display (dfa.initial-state dfa)) + (display ";\n")) + (display " node [shape = circle];\n") + (for-each (lambda (rule) + (display " ") + (display (rule.from rule)) + (display " -> ") + (display (rule.next rule)) + (display " [ label = ") + (cond ((char? (rule.value rule)) + (display #\") + (write (rule.value rule)) + (display #\")) + (else + (write (rule.value rule)))) + (display " ];\n")) + (dfa.rule-set dfa)) + (display "}\n")) + +;; DFA -> Fast DFA translation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (compile-dfa-to-fast-dfa d) + (define (char-small-enough? ch) + (<= 0 (char->integer ch) 127)) + (let* + ((states (quicksort! (list->vector (dfa.reachable-states d)) <=)) + (start-state (binary-search-vector states < (dfa.initial-state d))) + (end-array (vector-map (lambda (state) + (not (not (member state (dfa.end-states d))))) + states)) + (raw-rules (remove-duplicates equal? (dfa.rule-set d))) + (compiled-rules (vector-map + (lambda (state) + (let* + ((txn-table (make-vector 128 #f)) + (large-char-rules + (quicksort! + (list->vector + (filter-map (lambda (r) + (if (state=? state (rule.from r)) + (if (char-small-enough? (rule.value r)) + (begin + (vector-set! + txn-table + (char->integer (rule.value r)) + (binary-search-vector states + < + (rule.next r))) + #f) + (cons (char->integer (rule.value r)) + (binary-search-vector states + < + (rule.next r)))) + #f)) + raw-rules)) + (lambda (x y) (< (car x) (car y)))))) + (vector txn-table + (vector-map car large-char-rules) + (vector-map cdr large-char-rules)))) + states)) + (emit-directive (length (cdr emit-entry)) 2) + (let ((priority-order (quicksort-list (cdr emit-entry) emit-directive) dfa.input!) +(genproc-install 'fsm.reset! '(dfa) dfa.reset!) +(genproc-install 'fsm.done? '(dfa) dfa.done?) +(genproc-install 'fsm.failed? '(dfa) dfa.failed?) diff --git a/src/regex/fast-dfa.scm b/src/regex/fast-dfa.scm new file mode 100644 index 0000000..c1d8554 --- /dev/null +++ b/src/regex/fast-dfa.scm @@ -0,0 +1,229 @@ +(need algo/bsearch) + +(define (build-fast-dfa start-state end-array adjacency-matrix emit-vector) + (define bs + (make-binary-searcher vector-ref vector-length <)) + (define (char-small-enough? ch-as-int) + (<= 0 ch-as-int 127)) + (define (lookup-rule rule ch-as-int) + (if (char-small-enough? ch-as-int) + (vector-ref (vector-ref rule 0) ch-as-int) + (let ((index (bs (vector-ref rule 1) ch-as-int))) + (and index (vector-ref (vector-ref rule 2) index))))) + (define (false-to-minus-1 l) + (map (lambda (x) (if x x -1)) l)) + (define (run-length-encode int-list) + (define (add-entry current-count current result) + (if (= 0 current-count) + result + (append result (list current-count current)))) + (define (iter current-count current result rest) + (cond ((null? rest) + (add-entry current-count current result)) + ((= (car rest) current) + (iter (+ 1 current-count) current result (cdr rest))) + (else + (iter 1 + (car rest) + (add-entry current-count current result) + (cdr rest))))) + (if (null? int-list) + int-list + (iter 1 (car int-list) '() (cdr int-list)))) + (define (char-as-java-string char) + (cond ((char=? char #\') + "'\\''") + ((char=? char #\\) + "'\\\\'") + ((member char (string->list "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+[]{}|\";:,.<>/?")) + (string-append "'" (make-string 1 char) "'")) + (else + (string-append "((char)" (number->string (char->integer char)) ")")))) + (let* + ((current-state start-state) + (current-rule (vector-ref adjacency-matrix start-state)) + (vtab (vector + ;; reset! - method 0 + (lambda (dont-care) + (set! current-state start-state) + (set! current-rule (vector-ref adjacency-matrix + current-state))) + ;; input! - method 1 + (lambda (ch) + (if current-state + (begin (set! current-state + (lookup-rule current-rule + (char->integer ch))) + (if current-state + (set! current-rule + (vector-ref adjacency-matrix + current-state)) + (set! current-rule '()))))) + ;; done? - method 2 + (lambda (dont-care) + (and current-state + (vector-ref end-array current-state))) + ;; failed? - method 3 + (lambda (dont-care) + (not current-state)) + ;; serialize - method 4 + (lambda (dont-care) + `(build-fast-dfa (quote ,start-state) + (quote ,end-array) + (quote ,adjacency-matrix) + (quote ,emit-vector))) + ;; validate - method 5 + (lambda (dont-care) + (define (err . args) + (for-each display args) + (newline) + #f) + (and (< -1 start-state (vector-length end-array)) + (= (vector-length end-array) (vector-length adjacency-matrix)) + (accum-map + (lambda (a b) (and a b)) + #t + (lambda (rule) + (and + (or (= 3 (vector-length rule)) + (err "rule does not contain 3 entries")) + (or (= 128 (vector-length (vector-ref rule 0))) + (err "txn-table is not of length 128 " rule)) + (accum-map + (lambda (a b) (and a b)) + #t + (lambda (x) (or (or (not x) (< -1 x (vector-length end-array))) + (err "txn-table specifies invalid target " x " " rule))) + (vector->list (vector-ref rule 0))) + (or (let ((chars (vector->list (vector-ref rule 1)))) + (or (< (length chars) 2) + (apply < chars))) + (err "transition entries are not sorted " rule)) + (or (accum-map (lambda (a b) (and a b)) + #t + (lambda (x) (not (char-small-enough? x))) + (vector->list (vector-ref rule 1))) + (err "transition entries contain invalid characters " rule)) + (or (accum-map (lambda (a b) (and a b)) + #t + (lambda (x) (or (< -1 x (vector-length end-array)) + (err "transition entries contain invalid states " + rule))) + (vector->list (vector-ref rule 1)) )))) + (vector->list adjacency-matrix)))) + ;; emit - method 6 + (lambda (dont-care) + (vector-ref emit-vector current-state)) + ;; build java dfa - method 7 + (lambda (package import class-decoration class-name port) + (if package + (display (string-append "package " package ";\n\n") port)) + (if import + (display (string-append "import " import ";\n\n") port)) + (display (string-append (if class-decoration + (string-append class-decoration + " ") + "") + "class " + class-name + " {\n") port) + (display "\n" port) + ;; start state + (display (string-append " public static final int startState = " + (number->string start-state) + ";\n") + port) + (display "\n\n" port) + ;; end state map + (display (string-append " public static final boolean[] endStateMap = new boolean[] {\n") port) + (for-each (lambda (end?) + (display (string-append " " + (if end? "true" "false") + ",\n") + port)) + (vector->list end-array)) + (display " };\n" port) + (display "\n\n" port) + ;; adjacency matrix + (display " public static AdjacencyRule[] getAdjacencyRules() {\n" port) + (display " return new AdjacencyRule[] {\n" port) + (for-each (lambda (adjacency-rule) + (let ((adjacency-table (vector-ref adjacency-rule 0)) + (char-table (vector-ref adjacency-rule 1)) + (char-map (vector-ref adjacency-rule 2))) + (display " new AdjacencyRule(\n" port) + (display (string-append " new int[] {" + (apply string-append + (map (lambda (x) + (string-append (number->string x) ", ")) + (run-length-encode (false-to-minus-1 (vector->list adjacency-table))))) + "}") + port) + (if (not (zero? (vector-length char-map))) + (begin + (display ",\n" port) + (display (string-append " new char[] {" + (apply string-append + (map (lambda (x) + (string-append (char-as-java-string x) ", ")) + (vector->list char-table))) + "},\n") + port) + (display (string-append " new int[] {" + (apply string-append + (map (lambda (x) + (string-append (if x (number->string x) "-1") ", ")) + (vector->list char-map))) + "}") + port))) + (display "\n ),\n\n" port))) + (vector->list adjacency-matrix)) + (display " };\n" port) + (display " }\n" port) + (display "\n\n" port) + ;; emit vector + (display " public static final String[] emitMap = new String[] {\n" port) + (for-each (lambda (entry) + (display " " port) + (if (symbol? entry) + (write (symbol->string entry) port) + (display "null" port)) + (display ",\n" port)) + (vector->list emit-vector)) + (display " };\n" port) + (display "\n\n" port) + ;; end class + (display "}\n" port)) + )) ;; vtab + ) ;; let + (lambda (method . args) + (apply (vector-ref vtab method) args)))) ;; build-fast-dfa + +(define (fast-dfa-reset! fast-dfa) + (fast-dfa 0 '())) + +(define (fast-dfa-input! fast-dfa char) + (fast-dfa 1 char)) + +(define (fast-dfa-done? fast-dfa) + (fast-dfa 2 '())) + +(define (fast-dfa-failed? fast-dfa) + (fast-dfa 3 '())) + +(define (fast-dfa-serialize fast-dfa) + (fast-dfa 4 '())) + +(define (fast-dfa-validate fast-dfa) + (fast-dfa 5 '())) + +(define (fast-dfa-emit fast-dfa) + (fast-dfa 6 '())) + +(define (fast-dfa-serialize-java fast-dfa + package + import + class-decoration + class-name + port) + (fast-dfa 7 package import class-decoration class-name port)) diff --git a/src/regex/fsm.scm b/src/regex/fsm.scm new file mode 100644 index 0000000..23f0c64 --- /dev/null +++ b/src/regex/fsm.scm @@ -0,0 +1,15 @@ +(define (fsm? obj) + (genproc-invoke 'fsm? obj)) + +(define (fsm.input! fsm obj) + (genproc-invoke 'fsm.input! fsm obj)) + +(define (fsm.reset! fsm) + (genproc-invoke 'fsm.reset! fsm)) + +(define (fsm.done? fsm) + (genproc-invoke 'fsm.done? fsm)) + +(define (fsm.failed? fsm) + (genproc-invoke 'fsm.failed? fsm)) + diff --git a/src/regex/genlex.scm b/src/regex/genlex.scm new file mode 100644 index 0000000..7d7fd41 --- /dev/null +++ b/src/regex/genlex.scm @@ -0,0 +1,71 @@ +(need regex/regex) + +(define (generate-lexer description ignored) + (define (validate a-dfa) + (or (fast-dfa-validate a-dfa) + (error "Failed to validate regex DFA")) + a-dfa) + (let ((big-regex (cons ': (map (lambda (to-emit regex) + (list ':emit + to-emit + (index-of to-emit equal? (map car description)) + regex)) + (map car description) + (map cadr description))))) + (let ((big-dfa (validate (compile-regex big-regex)))) + (list big-dfa ignored)))) + +(define (write-lexer generated-lexer dfa-symbol entrypoint-symbol port) + (let ((big-dfa (car generated-lexer))) + (let ((code `((need regex/dfa) + (need regex/genlex) + (define ,dfa-symbol ,(fast-dfa-serialize big-dfa)) + (define ,entrypoint-symbol + (let ((main-dfa ,dfa-symbol)) + (lambda (input-port) + (run-generated-lexer main-dfa + (quote ,(list-ref generated-lexer 1)) + input-port))))))) + (for-each (lambda (code) + (write code port) + (newline port)) + code)))) + +(define (write-java-lexer generated-lexer . args) + (apply write-java-lexer-from-dfa (car generated-lexer) args)) + +(define (write-java-lexer-from-dfa main-dfa . args ) + (apply fast-dfa-serialize-java main-dfa args)) + +(define (run-lexer generated-lexer input-port) + (let ((main-dfa (list-ref generated-lexer 0)) + (ignored-tokens (list-ref generated-lexer 1))) + (run-generated-lexer main-dfa ignored-tokens input-port))) + +(define (run-generated-lexer main-dfa ignored-tokens input-port) + (define result '()) + (define (iter line column) + (define (process-match in) + (let ((value (car in)) + (token (cadr in))) + (if (not (member token ignored-tokens)) + (set! result (cons (list token value line column) + result))) + (iter (list-ref in 2) (list-ref in 3)))) +; (for-each display (list ";; iter (" line "," column ")\n")) + (if (not (eof-object? (peek-char input-port))) + (let ((in (regex-match-port-line-column main-dfa + input-port + line + column))) + (cond ((eqv? '*lexer-error* (car in)) + in) + (else + (process-match in)))) + (cons line column))) +; (display ";; run-generated-lexer\n") + (let ((res (iter 0 0))) + (if (and (pair? res) + (eqv? '*lexer-error* (car res))) + res + (reverse (cons (list '$ "" (car res) (cdr res)) result))))) diff --git a/src/regex/nfa.scm b/src/regex/nfa.scm new file mode 100644 index 0000000..41879b0 --- /dev/null +++ b/src/regex/nfa.scm @@ -0,0 +1,325 @@ +(need util/list) +(need util/string) +(need regex/fsm) +(need regex/dfa) + +;; NFA Rule interface ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (nfa-rule from value to) + (vector from value to)) +(define (nfa-lambda-rule from to) + (vector from to)) +(define (nfa-rule.lambda? nfa-rule) + (and (vector? nfa-rule) (= 2 (vector-length nfa-rule)))) +(define (nfa-rule.from nfa-rule) + (vector-ref nfa-rule 0)) +(define (nfa-rule.from? nfa-rule s) + (state=? s (nfa-rule.from nfa-rule))) +(define (nfa-rule.to nfa-rule) + (cond ((nfa-rule.lambda? nfa-rule) (vector-ref nfa-rule 1)) + (else (vector-ref nfa-rule 2)))) +(define (nfa-rule.value nfa-rule) + (if (nfa-rule.lambda? nfa-rule) + (error "Lambda (empty-string) rule has no value -- NFA-RULE.VALUE" + nfa-rule)) + (vector-ref nfa-rule 1)) +(define (nfa-rule.value? nfa-rule value) + (or (equal? (nfa-rule.value nfa-rule) value) + (and (string? (nfa-rule.value nfa-rule)) + (char? value) + (strchr (nfa-rule.value nfa-rule) value)))) + +(define (nfa-rule-filter p? nfa-rules) + (remove-duplicate-states (map nfa-rule.to (filter p? nfa-rules)))) + +;; NFA interface ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (nfa? obj) + (tagged? 'nfa obj)) + +(define (nfa.current-states nfa) + ((safe-contents 'nfa nfa) 'get-current)) +(define (nfa.emit-rule-set nfa) + ((safe-contents 'nfa nfa) 'get-emit-rules)) +(define (nfa.current-emitted-values nfa) + (let ((result '())) + ((safe-contents 'nfa nfa) 'emit + (lambda (x) (set! result (cons x result)))) + result)) +(define (nfa.get-emitted-values-for-states nfa states) + (let ((result '()) + (rules (nfa.emit-rule-set nfa))) + (for-each (lambda (state) + (let ((item (assoc state rules))) + (if (and item + (not (member item result))) + (set! result (cons (cdr item) result))))) + states) + result)) +(define (nfa.initial-state nfa) + ((safe-contents 'nfa nfa) 'get-initial)) +(define (nfa.final-states nfa) + ((safe-contents 'nfa nfa) 'get-final)) +(define (nfa.rule-set nfa) + ((safe-contents 'nfa nfa) 'get-rules)) +(define (nfa.input! nfa obj) + ((safe-contents 'nfa nfa) 'input obj)) +(define (nfa.reset! nfa) + ((safe-contents 'nfa nfa) 'reset)) +(define (nfa.failed? nfa) + (null? (nfa.current-states nfa))) +(define (nfa.done? nfa) + (and (not (nfa.failed? nfa)) + (let ((isect + (intersect-lists state=? + (nfa.current-states nfa) + (nfa.final-states nfa)))) + (and (not (null? isect)) isect)))) + +;; Advanced NFA routines ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (nfa.reachable-states nfa) + (depth-first-search state=? + (nfa.initial-state nfa) + (lambda (state) + (map nfa-rule.to + (filter (lambda (rule) + (nfa-rule.from? rule state)) + (nfa.rule-set nfa)))))) + +(define (nfa.referenced-states nfa) + (remove-duplicate-states + (append (cons (nfa.initial-state nfa) + (nfa.final-states nfa)) + (map nfa-rule.from (nfa.rule-set nfa)) + (map nfa-rule.to (nfa.rule-set nfa))))) + +(define (nfa:possible-transitions nfa state) + (remove-duplicates + equal? + (append-map + (lambda (rule) + (let ((val (nfa-rule.value rule))) + (cond ((string? val) + (string->list val)) + ((char? val) + (list val)) + (else + (error "Unrecognized NFA rule value: " val))))) + (filter (lambda (rule) + (and (not (nfa-rule.lambda? rule)) + (nfa-rule.from? rule state))) + (nfa.rule-set nfa))))) + +(define (nfa:possible-transitions* nfa statelist) + (remove-duplicates + equal? + (append-map (lambda (state) (nfa:possible-transitions nfa state)) + statelist))) + + + +(define (nfa:lambda-closure nfa state) + (depth-first-search state=? + state + (lambda (state) + (remove-duplicate-states + (nfa-rule-filter (lambda (rule) + (and (nfa-rule.lambda? rule) + (nfa-rule.from? rule state))) + (nfa.rule-set nfa)))))) + +(define (nfa:next nfa state obj) + (define (matching-rule? rule) + (and (nfa-rule.from? rule state) + (not (nfa-rule.lambda? rule)) + (nfa-rule.value? rule obj))) + (remove-duplicate-states + (append-map (lambda (state) (nfa:lambda-closure nfa state)) + (nfa-rule-filter matching-rule? (nfa.rule-set nfa))))) + +(define (nfa:next* nfa states obj) + (remove-duplicate-states + (append-map (lambda (state) (nfa:lambda-closure nfa state)) + (append-map (lambda (state) (nfa:next nfa state obj)) + states)))) + +;; NFA constructor ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (build-nfa initial-state final-states rules emit-rules) + (define (lambda-closure state) + (depth-first-search state=? + state + (lambda (state) + (remove-duplicate-states + (nfa-rule-filter (lambda (rule) + (and (nfa-rule.lambda? rule) + (nfa-rule.from? rule state))) + rules))))) + (let ((cur (lambda-closure initial-state))) + (define (get-current) + cur) + (define (reset) + (set! cur (lambda-closure initial-state))) + (define (input obj) + (define (next state) + (define (matching-rule? rule) + (and (nfa-rule.from? rule state) + (not (nfa-rule.lambda? rule)) + (nfa-rule.value? rule obj))) + (nfa-rule-filter matching-rule? rules)) + (set! cur + (remove-duplicate-states + (append-map lambda-closure (append-map next cur)))) + cur) + (define (get-initial) + initial-state) + (define (get-final) + final-states) + (define (get-rules) + rules) + (define (get-emit-rules) + emit-rules) + (define (emit receive-result) + (for-each (lambda (state) + (let ((result (assoc state emit-rules))) + (if result + (receive-result (cdr result))))) + (get-current))) + (define (nfa-dispatch sym . args) + (apply (case sym + ((get-current) get-current) + ((get-initial) get-initial) + ((get-final) get-final) + ((input) input) + ((reset) reset) + ((emit) emit) + ((get-emit-rules) get-emit-rules) + ((get-rules) get-rules)) + args)) + (tag 'nfa nfa-dispatch))) + +;; NFA transforms ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (nfa->dfa nfa) + (define unique-state (let ((s -1)) (lambda () (set! s (+ s 1)) s))) + + (define (possible-transitions* states) + (nfa:possible-transitions* nfa states)) + + (define (dfa-transformer nfa-states) + (lambda (state) (index-of state + (list-set-comparator equal?) + nfa-states))) + + (define (compute-final-states statelists) + (remove-duplicates + (list-set-comparator state=?) + (filter (lambda (statelist) + (not (null? (intersect-lists state=? + statelist + (nfa.final-states nfa))))) + statelists))) + + (define (create-dfa visited rules) + (dfa-transform + (build-dfa (nfa:lambda-closure nfa (nfa.initial-state nfa)) + (compute-final-states visited) + rules + (filter-map + (lambda (statelist) + (let ((emit + (nfa.get-emitted-values-for-states nfa statelist))) + (and (not (null? emit)) + (cons statelist emit)))) + visited)) + (dfa-transformer visited)) + ) + + (define (iter queue visited rules) + + (define (statelists-to-queue cur-statelist) + (map (lambda (obj) + (nfa:next* nfa cur-statelist obj)) + (possible-transitions* cur-statelist))) + + (define (new-rules cur-statelist) + (map + (lambda (obj) + (nfa-rule cur-statelist obj (nfa:next* nfa cur-statelist obj))) + (possible-transitions* cur-statelist))) + + (define (visited? statelist) + (list-contains? (list-set-comparator state=?) + statelist + visited)) + + (define (queue-statelists list-of-statelists) + (union-lists (list-set-comparator state=?) + (subtract-lists (list-set-comparator state=?) + list-of-statelists + visited) + (cdr queue))) + + (define (queue-rules new-rules) + (append new-rules rules)) + + (if (null? queue) + (create-dfa visited rules) + (let ((cur-statelist (car queue))) +;(display "Current: ") (write cur-statelist) (newline) +;(display "Queue: ") (write queue) (newline) +;(display "Visited: ") (write visited) (newline) +;(display "Rules: ") (write rules) (newline) +;(newline) +;(newline) +;(newline) + (iter (queue-statelists (statelists-to-queue cur-statelist)) + (cons cur-statelist visited) + (queue-rules (new-rules cur-statelist)))))) + (iter (list (nfa:lambda-closure nfa (nfa.initial-state nfa))) + '() + '())) + +;; (define +;; nex (build-nfa #\a (list #\b) +;; (list (nfa-rule #\a 3 #\b) +;; (nfa-rule #\a 3 #\c) +;; (nfa-lambda-rule #\a #\b)) +;; '((#\a . 0) +;; (#\b . 1)))) + +;; NFA graphviz integration ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (nfa.graphviz nfa) + (display "digraph nondeterministic_finite_automaton {\n") + (display " rankdir=LR;\n") + (begin (display " node [shape = doublecircle]; ") + (display (nfa.initial-state nfa)) + (display ";\n")) + (display " node [shape = circle];\n") + (for-each (lambda (rule) + (display " ") + (display (nfa-rule.from rule)) + (display " -> ") + (display (nfa-rule.to rule)) + (display " [ label = ") + (if (nfa-rule.lambda? rule) + (write "***") + (cond ((char? (nfa-rule.value rule)) + (display #\") + (write (nfa-rule.value rule)) + (display #\")) + (else + (write (nfa-rule.value rule))))) + (display " ];\n")) + (nfa.rule-set nfa)) + (display "}\n")) + +;; Generic Procedure setup ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(genproc-install 'fsm? '(nfa) nfa?) +(genproc-install 'fsm.input! '(nfa ) nfa.input!) +(genproc-install 'fsm.reset! '(nfa) nfa.reset!) +(genproc-install 'fsm.done? '(nfa) nfa.done?) +(genproc-install 'fsm.failed? '(nfa) nfa.failed?) diff --git a/src/regex/regex.scm b/src/regex/regex.scm new file mode 100644 index 0000000..1c3fc40 --- /dev/null +++ b/src/regex/regex.scm @@ -0,0 +1,173 @@ +(need scheme/tag) +(need regex/nfa) +(need regex/dfa) +(need regex/compile) + +(define (make-regex-syntax check compiler) + (tag 'regex-syntax (list check compiler))) +(define (regex-syntax.check syntax) + (car (contents syntax))) +(define (regex-syntax.compiler syntax) + (cadr (contents syntax))) + +(define *regex-syntax-table* '()) +(define (install-regex-syntax! syntax) + (set! *regex-syntax-table* + (cons syntax *regex-syntax-table*))) + +(define (lookup-regex-syntax rgx) + (define (iter l) + (cond ((null? l) #f) + (((regex-syntax.check (car l)) rgx) (car l)) + (else (iter (cdr l))))) + (iter *regex-syntax-table*)) + +(define (lookup-regex-compiler rgx) + (let ((syn (lookup-regex-syntax rgx))) + (and syn (regex-syntax.compiler syn)))) + +(define (compile-subregex rgx) + (let ((compiler (lookup-regex-compiler rgx))) + (let ((res (and compiler (compiler rgx)))) + (if (not (nfa? res)) + (error "Result of compilation should be a NFA -- COMPILE-SUBREGEX" + rgx res) + res)))) + +(define (compile-regex rgx) + (if (procedure? rgx) + (begin (fast-dfa-reset! rgx) + rgx) + (let ((res (compile-subregex rgx))) + (if (not (nfa? res)) + (error "Reuslt of compilation should be a NFA -- COMPILE-REGEX" + rgx res)) + (compile-dfa-to-fast-dfa (nfa->dfa res))))) + +(define (define-regex-syntax check compiler) + (install-regex-syntax! + (make-regex-syntax check compiler))) + +(define (define-regex-keyword-syntax keyword compiler) + (define-regex-syntax + (lambda (rgx) (and (list? rgx) (eqv? keyword (car rgx)))) + (lambda (rgx) (compiler (map compile-subregex (cdr rgx)))))) + +(define (true? x) (not (eqv? #f x))) + +(define (regex-whole-match rgx string) + (let ((a-dfa (compile-regex rgx))) + (for-each (lambda (char) (fast-dfa-input! a-dfa char)) + (string->list string)) + (fast-dfa-done? a-dfa))) + +(define (test-regex rgx string expected) + (let ((res (true? (regex-whole-match rgx string)))) + (if (not (equal? expected res)) + (error (format "~ ~ => ~, expected ~" rgx string res expected))))) + +(define (regex-match-from regex string idx) + (let ((a-dfa (compile-regex regex))) + (define (return idx len) + (list idx (+ idx len))) + (define (try-match idx) + (define (iter cur len) + (if (>= cur (string-length string)) + (and (fast-dfa-done? a-dfa) (return idx len)) + (let ((pre-done? (fast-dfa-done? a-dfa))) + (fast-dfa-input! a-dfa (string-ref string cur)) + (cond ((and pre-done? (not (zero? len)) + (fast-dfa-failed? a-dfa)) + (return idx len)) + ((fast-dfa-failed? a-dfa) + (try-match (+ idx 1))) + (else + (iter (+ cur 1) (+ len 1))))))) + (fast-dfa-reset! a-dfa) + (iter idx 0)) + (try-match 0))) + +(define (regex-match regex string) + (regex-match-from regex string 0)) + +(define (regex-matching-string regex string) + (let ((match (regex-match regex string))) + (and match (substring string (car match) (cadr match))))) + +(define (regex-match-complete? regex string) + (let ((match (regex-matching-string regex string))) + (and match (string=? string match)))) + +(define (regex-match-port-line-column regex port line column) + (let ((a-dfa (compile-regex regex))) + (define (return res output line column) + (list (list->string (reverse res)) output line column)) + (define (return-error res char line column) + (list '*lexer-error* + (list->string (reverse (cons char res))) + line + column)) + (define (next-line line char) + (if (char=? char #\newline) + (+ line 1) + line)) + (define (next-column col char) + (if (char=? char #\newline) + 0 + (+ col 1))) + (define (iter res line column) + (let ((char (peek-char port))) + (if (eof-object? char) + (if (fast-dfa-done? a-dfa) + (return res (fast-dfa-emit a-dfa) line column) + (return-error res char line column)) + (let ((pre-done (fast-dfa-done? a-dfa)) + (pre-done-output (fast-dfa-emit a-dfa))) + (fast-dfa-input! a-dfa char) + (cond ((and pre-done (not (null? res)) + (fast-dfa-failed? a-dfa)) + (return res pre-done-output line column)) + ((fast-dfa-failed? a-dfa) + (return-error res char line column)) + (else (let ((char (read-char port))) + (iter (cons char res) + (next-line line char) + (next-column column char))))))))) + (iter '() line column))) + +(define (regex-match-port regex port) + (let ((res (regex-match-port-line-column regex port 0 0))) + (and res (car res)))) + +(define-regex-syntax char? compile-char) +(define-regex-syntax string? compile-string) +(define-regex-syntax symbol? (lambda (rgx) (compile-string (symbol->string rgx)))) +(define-regex-syntax number? (lambda (rgx) (compile-string (number->string rgx)))) +(define-regex-syntax (lambda (x) + (and (list? x) + (= 2 (length x)) + (eqv? '@ (list-ref x 0)) + (string? (list-ref x 1)))) + compile-optional-string) +(define-regex-syntax (lambda (stmt) + (and (list? stmt) + (= 4 (length stmt)) + (eqv? ':emit (list-ref stmt 0)))) + (lambda (stmt) + (compile-emit (compile-subregex (list-ref stmt 3)) ; <- nfa + (list-ref stmt 1) ; <- value-to-emit + (list-ref stmt 2)))) ; <- emit-priority + +(define-regex-keyword-syntax '& compile-append) +(define-regex-keyword-syntax ': compile-or) +;(define-regex-keyword-syntax '@ compile-or) +(define-regex-keyword-syntax '* + (lambda (list-of-nfas) (compile-* (compile-append list-of-nfas)))) +(define-regex-keyword-syntax '+ + (lambda (list-of-nfas) (compile-+ (compile-append list-of-nfas)))) +(define-regex-keyword-syntax '^ + (lambda (list-of-nfas) (compile-append (map compile-optional + list-of-nfas)))) +(define-regex-keyword-syntax '^& + (lambda (list-of-nfas) (compile-optional + (compile-append list-of-nfas)))) diff --git a/src/repl.scm b/src/repl.scm new file mode 100644 index 0000000..daf0742 --- /dev/null +++ b/src/repl.scm @@ -0,0 +1,2 @@ +(define (current-command-line-arguments) (vector "empty.scm")) +(load "run.scm") diff --git a/src/rtl/CsharpRtl.cs b/src/rtl/CsharpRtl.cs new file mode 100644 index 0000000..788d046 --- /dev/null +++ b/src/rtl/CsharpRtl.cs @@ -0,0 +1,57 @@ +class CsharpRtl +{ + public static void Main( string[] args ) + { + {} + } +} + +class String +{ + char[] c; + + public String( char[] chars ) + { + c = chars; + } + + virtual public int length() + { + return c.length; + } + + virtual public char charAt( int i ) + { + return c[i]; + } + + virtual public char[] toCharArray() { + return c; + } + + virtual public String append( String s ) + { + int len; + int idx; + char[] newchars; + + len = c.length + s.length(); + newchars = new char[len]; + + idx = 0; + while( idx < c.length ) + { + newchars[idx] = c[idx]; + idx = idx + 1; + } + + idx = 0; + while( idx < s.length() ) + { + newchars[idx+c.length] = s.charAt( idx ); + idx = idx + 1; + } + + return new String( newchars ); + } +} diff --git a/src/rtl/JavaRtl.java b/src/rtl/JavaRtl.java new file mode 100644 index 0000000..c984aa1 --- /dev/null +++ b/src/rtl/JavaRtl.java @@ -0,0 +1,57 @@ +class JavaRtl +{ + public static void main( String[] args ) + { + {} + } +} + +class String +{ + char[] c; + + public String( char[] chars ) + { + c = chars; + } + + public int length() + { + return c.length; + } + + public char charAt( int i ) + { + return c[i]; + } + + public char[] toCharArray() { + return c; + } + + public String append( String s ) + { + int len; + int idx; + char[] newchars; + + len = c.length + s.length(); + newchars = new char[len]; + + idx = 0; + while( idx < c.length ) + { + newchars[idx] = c[idx]; + idx = idx + 1; + } + + idx = 0; + while( idx < s.length() ) + { + newchars[idx+c.length] = s.charAt( idx ); + idx = idx + 1; + } + + return new String( newchars ); + } +} diff --git a/src/rtl/c-rtlheap.sasm b/src/rtl/c-rtlheap.sasm new file mode 100644 index 0000000..2e3dbb0 --- /dev/null +++ b/src/rtl/c-rtlheap.sasm @@ -0,0 +1,147 @@ +;; c-rtlheap.sasm +;; Heap stub routines to interface the C stub to the compiler system + +(export cp-rtl-malloc-failed) +(export rtl-gc-mark-pointer) +(export cp-rtl-malloc) +(export cp-rtl-mark-all-roots) +(export cp-rtl-add-global-root-range) + +(extern gc-mark-pointer) +(extern gc-mark-stack-roots) +(extern mm-rtl-heap-end-mark-global-vars) +(extern mm-rtl-heap-begin-mark-global-vars) +(extern gc-mark-memory-range) +(extern cp-rtl-base-malloc) +(extern c-fail-malloc) +(extern c-fail-add-heap) + +(global rtl-global-var-roots (const 0)) + +(function (name cp-rtl-add-global-root-range) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; arg 0 - start of the range + ;; deprecated - arg 1 - end of the range + ;; + ;; rtl-global-var-roots is a linked list of all of the + ;; ranges of global variables. + ;; + ;; offset 0 - free space to store the next range pointer + ;; offset 1 - end pointer (should already be filled in statically by codegen) + ;; + (assign (reg accum) (arg 0)) + + ;; check to make sure the next pointer is empty + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (branch-zero (label cp-rtl-add-global-root-range/ok1) (reg operand)) + + (perform (op break)) + + (label cp-rtl-add-global-root-range/ok1) + + (assign (reg operand) (op load-array) (const rtl-global-var-roots) (const 0)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + + ;; the following should not be necessary since it + ;; should already be filled in by codegen. + ;; + ;;(perform (op store-array) (temp start) (const 1) (temp end)) + + (perform (op store-array) (const rtl-global-var-roots) (const 0) (reg accum)) + + (label cp-rtl-add-global-root-range/done) + (perform (op pop-frame)) + (return (const 1)))) + +(function (name cp-rtl-mark-all-roots) + (locals 1) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 1)) + + (perform (op call) (label gc-mark-stack-roots)) + + (assign (reg accum) (label mm-rtl-heap-end-mark-global-vars)) + (push (reg accum)) + (assign (reg accum) (label mm-rtl-heap-begin-mark-global-vars)) + (push (reg accum)) + (perform (op call) (label gc-mark-memory-range)) + + (assign (reg accum) (op load-array) (const rtl-global-var-roots) (const 0)) + + (label cp-rtl-mark-all-roots/globals-loop) + (branch-zero (label cp-rtl-mark-all-roots/globals-done) (reg accum)) + + ;; the start of the range is 2 pointers past the global vars header: + ;; + ;; header_pointer: + ;; <1-pointer> + ;; end_pointer: + ;; <1-pointer> end_mark_globals + ;; data_pointer: ;; <-- first data pointer here + ;; + ;; end_mark_globals: + ;; + (assign (reg index) (op add-pointer) (reg accum) (const 2)) + + ;; push the end of the range (arg 2) + (assign (reg operand) (op load-array) (reg accum) (const 1)) + (push (reg operand)) + + ;; push the start of the range (arg 1) + (push (reg index)) + + ;; get the next pointer and save it in a local variable across the function call + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (assign (local 0) (reg operand)) + + ;; call the mark-memory-range function + (perform (op call) (label gc-mark-memory-range)) + + (assign (reg accum) (local 0)) + (goto (label cp-rtl-mark-all-roots/globals-loop)) + + (label cp-rtl-mark-all-roots/globals-done) + (perform (op pop-frame)) + (return (const 0)))) + +;; Dispatches directly to gc-mark-pointer. +(function (name rtl-gc-mark-pointer) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 0)) + (perform (op call) (const gc-mark-pointer)) + + (perform (op pop-frame)) + (return (const 0)))) + +(function (name cp-rtl-malloc-failed) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; Call a C function that will print out an error + ;; message and abort. + (push (arg 0)) + (perform (op call) (const c-fail-malloc)) + (pop (const 1)) + + (perform (op pop-frame)) + (return (const 1)))) + +(function (name cp-rtl-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; Call the underlying malloc function, result in accum. + (push (arg 0)) + (perform (op call) (const cp-rtl-base-malloc)) + + ;; Done. + (perform (op pop-frame)) + (return (const 1)))) diff --git a/src/rtl/debug.asm b/src/rtl/debug.asm new file mode 100644 index 0000000..1e7d4bc --- /dev/null +++ b/src/rtl/debug.asm @@ -0,0 +1,289 @@ + bits 32 + section .text + + global _debug_corruption + global _debug_corruption_id + global _debug_corruption_pointer + global _debug_corruption_watch + extern _mj_system_out_println + +_debug_corruption: + push eax + push ebx + push ecx + push edx + push edi + push esi + mov dword [_debug_corruption_arg], eax + inc dword [_debug_corruption_counter] + +_debug_corruption_proceed: + ;; jmp NEAR _debug_corruption_nonspecial + + ;; cmp [_debug_corruption_id], dword 1586 + ;; jnz NEAR _debug_corruption_nonspecial + + ;; cmp [_debug_corruption_counter], dword 4140 + ;; jnz NEAR _debug_corruption_nonspecial + + ;; mov eax, 73139125 + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch] + ;; mov eax, [eax] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_arg] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_arg] + ;; mov eax, [eax+4] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_arg] + ;; mov eax, [eax] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch] + ;; mov [_debug_corruption_watch_internal], eax + + ;; mov eax, 7575123 + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + +;; mov eax, [_debug_corruption_arg] +;; mov [_debug_corruption_pointer], eax + +;; mov eax, [_debug_corruption_id] +;; push eax +;; call _mj_system_out_println +;; add esp, 4 + +;; mov eax, [_debug_corruption_counter] +;; push eax +;; call _mj_system_out_println +;; add esp, 4 + +;; mov eax, [_debug_corruption_watch_internal] +;; push eax +;; call _mj_system_out_println +;; add esp, 4 + +;; mov eax, [_debug_corruption_watch_internal] +;; mov eax, [eax] +;; push eax +;; call _mj_system_out_println +;; add esp, 4 + +;; mov eax, [_debug_corruption_pointer] +;; push eax +;; call _mj_system_out_println +;; add esp, 4 + +;; mov eax, [eax] +;; push eax +;; call _mj_system_out_println +;; add esp, 4 + +;; mov eax, 1278127899 +;; push eax +;; call _mj_system_out_println +;; add esp, 4 + +;; jmp NEAR _debug_corruption_done + +_debug_corruption_nonspecial: + + ;; + ;; mov eax, [_debug_corruption_id] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + ;; + ;; mov eax, [_debug_corruption_counter] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + ;; + ;; + ;; mov eax, _debug_corruption_pointer + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch_internal] + ;; cmp eax, 0 + ;; jz _debug_corruption_done + + ;; mov eax, [_debug_corruption_watch_internal] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch_internal] + ;; mov eax, [eax] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch_internal] + ;; mov eax, [eax+4] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch_internal] + ;; cmp [eax+8], dword 0xbaadfeed + ;; jz _debug_corruption_done + + ;; mov eax, dword 234234234 + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_id] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_counter] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; int 3 + + ;; + ;; cmp [_debug_corruption_pointer], dword 0 + ;; jz _debug_corruption_done + ;; mov eax, [_debug_corruption_pointer] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_pointer] + ;; mov eax, [eax+4] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + ;; + ;; mov eax, [eax+4] + ;; cmp eax, 0xbaadfeed + ;; mov ebx, [_debug_corruption_watch_internal] + ;; cmp ebx, 0 + ;; jz _debug_corruption_done + ;; mov eax, [_debug_corruption_pointer] + ;; cmp eax, 0 + ;; jz _debug_corruption_done + + ;; mov eax, [_debug_corruption_watch_internal] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_watch_internal] + ;; mov eax, [eax] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_pointer] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov eax, [_debug_corruption_pointer] + ;; mov eax, [eax] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + + ;; mov ebx, [_debug_corruption_watch_internal] + ;; mov eax, [_debug_corruption_pointer] + ;; mov ebx, [ebx] + ;; cmp eax, ebx + ;; jnz _debug_corruption_done + ;; mov eax, dword 234234234 + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + ;; int 3 +_debug_corruption_done: + ;; mov eax, 22222222 + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + ;; ;; + ;; mov eax, 11111111 + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 + ;; + ;; mov eax, [_debug_corruption_pointer] + ;; mov eax, [eax+4] + ;; push eax + ;; call _mj_system_out_println + ;; add esp, 4 +_debug_corruption_bail2: +_debug_corruption_bail: + pop esi + pop edi + pop edx + pop ecx + pop ebx + pop eax + ret 0 + + section .data + +_debug_corruption_pointer: + dd 0 + dd 0 + dd 0 + dd 0 + +_debug_corruption_watch: + dd 0 + dd 0 + dd 0 + dd 0 + +_debug_corruption_watch_internal: + dd 0 + dd 0 + dd 0 + dd 0 + +_debug_corruption_arg: + dd 0 + dd 0 + dd 0 + dd 0 + +_debug_corruption_id: + dd 0 + dd 0 + dd 0 + dd 0 + +_debug_corruption_counter: + dd 0 + dd 0 + dd 0 + dd 0 diff --git a/src/rtl/gc-defines.sasm b/src/rtl/gc-defines.sasm new file mode 100644 index 0000000..c24789e --- /dev/null +++ b/src/rtl/gc-defines.sasm @@ -0,0 +1,17 @@ +;; rtl/gc-defines.sasm +;; Some constants for GCDW + +(define-symconst + (gcdw:done-mask #x0000ffff) + (gcdw:done-shift 0) + (gcdw:offset 1) + + (gcdw:mark-mask #x00010000) + (gcdw:mark-shift 16) + + (gcdw:leaf-mask #x00020000) + (gcdw:leaf-shift 17) + + (gcdw:array-mask #x80000000) + (gcdw:array-shift 31) + ) diff --git a/src/rtl/gc-externs.sasm b/src/rtl/gc-externs.sasm new file mode 100644 index 0000000..2590f76 --- /dev/null +++ b/src/rtl/gc-externs.sasm @@ -0,0 +1,16 @@ +;; externs common to all gc modules +(extern mm-heap-global-base) +(extern mm-heap-global-limit) +(extern mm-heap-assoc) +(extern mm-heap-sweep-area) +(extern root-heap-pointer) +(extern rtl-gc-mark-pointer) +(extern cp-rtl-mark-all-roots) +(extern mj-system-out-println) +(extern mj-system-out-println-string) +(extern mm-rtl-heap-begin-mark-global-vars) +(extern mm-rtl-heap-end-mark-global-vars) +(extern gc-root-stack-limit) +(extern gc-root-stack-base) +(extern gc-heap-base) +(extern gc-heap-limit) diff --git a/src/rtl/gc-invoke.sasm b/src/rtl/gc-invoke.sasm new file mode 100644 index 0000000..f3649e7 --- /dev/null +++ b/src/rtl/gc-invoke.sasm @@ -0,0 +1,20 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(export gc-invoke) +(extern gc-sweep) +(extern cp-rtl-mark-all-roots) + +(function + (name gc-invoke) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op call) (const cp-rtl-mark-all-roots)) + (perform (op call) (const gc-sweep)) + + (perform (op pop-frame)) + (return (const 0)))) + diff --git a/src/rtl/gc-mark-array.sasm b/src/rtl/gc-mark-array.sasm new file mode 100644 index 0000000..c3787c1 --- /dev/null +++ b/src/rtl/gc-mark-array.sasm @@ -0,0 +1,61 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(export gc-mark-array) + +(function + (name gc-mark-array) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; test if we have already marked this object + + (assign (temp gcdw) (op load-array) (arg 0) (const -1)) + + ;; (push (const #xdeadc0dd)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp gcdw)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + + (assign (temp test) (op bit-and) (temp gcdw) (symconst gcdw:mark-mask)) + (branch-nonzero (label gc-mark-array/end) (temp test)) + + ;; we haven't; mark it + +; ;; begin DEBUG +; (perform (op debug-out) (const "gc-mark-array ") (arg 0)) +; ;; end DEBUG + + (assign (temp gcdw) (op bit-or) (temp gcdw) (symconst gcdw:mark-mask)) + (perform (op store-array) (arg 0) (const -1) (temp gcdw)) + + ;; figure out how many child objects it has + + (assign (temp n-items) (op load-array) (arg 0) (const -2)) + (assign (temp members) (arg 0)) + + ;; loop through the children and mark them (no pointer reversal yet) + + (assign (temp item) (const 0)) + (label gc-mark-array/begin) + (assign (temp test) (op less-than) (temp item) (temp n-items)) + (branch-zero (label gc-mark-array/end) (temp test)) + + (assign (temp ptr) (op load-array) (temp members) (temp item)) + (push (temp ptr)) + (perform (op call) (const rtl-gc-mark-pointer)) + (pop (const 1)) + + (assign (temp item) (op add) (temp item) (const 1)) + (goto (label gc-mark-array/begin)) + + (label gc-mark-array/end) + (perform (op pop-frame)) + (return (const 1)))) + diff --git a/src/rtl/gc-mark-class.sasm b/src/rtl/gc-mark-class.sasm new file mode 100644 index 0000000..1c6f5bb --- /dev/null +++ b/src/rtl/gc-mark-class.sasm @@ -0,0 +1,48 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(export gc-mark-class-instance) + +(function + (name gc-mark-class-instance) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; test if we have already marked this object + + (assign (temp gcdw) (op load-array) (arg 0) (const 1)) + (assign (temp test) (op bit-and) (temp gcdw) (symconst gcdw:mark-mask)) + (branch-nonzero (label gc-mark-class-instance/end) (temp test)) + + ;; we haven't; mark it + + (assign (temp gcdw) (op bit-or) (temp gcdw) (symconst gcdw:mark-mask)) + (perform (op store-array) (arg 0) (const 1) (temp gcdw)) + + ;; figure out how many child objects it has + + (assign (temp class-descriptor) (op load-array) (arg 0) (const 0)) + (assign (temp n-items) (op load-array) (temp class-descriptor) (const 0)) + (assign (temp members) (op add-pointer) (arg 0) (const 2)) + + ;; loop through the children and mark them (no pointer reversal yet) + + (assign (temp item) (const 0)) + (label gc-mark-class-instance/begin) + (assign (temp test) (op less-than) (temp item) (temp n-items)) + (branch-zero (label gc-mark-class-instance/end) (temp test)) + + (assign (temp ptr) (op load-array) (temp members) (temp item)) + (push (temp ptr)) + (perform (op call) (const rtl-gc-mark-pointer)) + (pop (const 1)) + + (assign (temp item) (op add) (temp item) (const 1)) + (goto (label gc-mark-class-instance/begin)) + + (label gc-mark-class-instance/end) + (perform (op pop-frame)) + (return (const 1)))) + diff --git a/src/rtl/gc-mark-range.sasm b/src/rtl/gc-mark-range.sasm new file mode 100644 index 0000000..8905bfe --- /dev/null +++ b/src/rtl/gc-mark-range.sasm @@ -0,0 +1,48 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(export gc-mark-memory-range) + +(function + (name gc-mark-memory-range) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + +; ;; begin DEBUG +; (assign (reg accum) (label gc-debug-message-3)) +; (push (reg accum)) +; (perform (op call) (const mj-system-out-println-string)) +; (pop (const 1)) +; (push (arg 0)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; (push (arg 1)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; ;; end DEBUG + + (assign (temp range-base) (arg 0)) + (assign (temp range-limit) (arg 1)) + + (perform (op call) (const mm-heap-global-base)) + (perform (op store-array) (const gc-heap-base) (const 0) (reg accum)) + + (perform (op call) (const mm-heap-global-limit)) + (perform (op store-array) (const gc-heap-limit) (const 0) (reg accum)) + + (label gc-mark-memory-range/begin) + (assign (temp test) (op less-than) (temp range-base) (temp range-limit)) + (branch-zero (label gc-mark-memory-range/end) (temp test)) + + (assign (temp ptr) (op load-array) (temp range-base) (const 0)) + (push (temp ptr)) + (perform (op call) (const rtl-gc-mark-pointer)) + (pop (const 1)) + (assign (temp range-base) (op add-pointer) (temp range-base) (const 1)) + (goto (label gc-mark-memory-range/begin)) + + (label gc-mark-memory-range/end) + (perform (op pop-frame)) + (return (const 2)))) diff --git a/src/rtl/gc-mark.sasm b/src/rtl/gc-mark.sasm new file mode 100644 index 0000000..c5887a4 --- /dev/null +++ b/src/rtl/gc-mark.sasm @@ -0,0 +1,203 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(export gc-mark-pointer) +(extern gc-mark-array) +(extern gc-mark-class-instance) + +(function + (name gc-mark-pointer) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; (push (const #xdeadc0da)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (arg 0)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + +; ;; begin DEBUG +; (perform (op debug-out) (const "GC-mark-pointer: ") (arg 0)) +; ;; end DEBUG + + (branch-zero (label gc-mark-pointer/end) (arg 0)) + + ;; query the global heap range + + (assign (temp base) (op load-array) (const gc-heap-base) (const 0)) + (assign (temp limit) (op load-array) (const gc-heap-limit) (const 0)) + + ;; test to make sure the pointer falls within that range + + (assign (temp test) (op less-than) (arg 0) (temp base)) + (branch-nonzero (label gc-mark-pointer/end) (temp test)) + + (assign (temp test) (op less-than) (arg 0) (temp limit)) + (branch-zero (label gc-mark-pointer/end) (temp test)) + + ;; it does, so look up a specific heap + (push (arg 0)) + (perform (op call) (const mm-heap-assoc)) + (assign (temp heap) (reg accum)) + (branch-zero (label gc-mark-pointer/end) (temp heap)) + + ;; (push (const ">>> gc-mark-pointer")) + ;; (perform (op call) (const mj-system-out-println-string)) + ;; (pop (const 1)) + + ;; (push (const #xdeadc0de)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (arg 0)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp heap)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (const "<<< gc-mark-pointer")) + ;; (perform (op call) (const mj-system-out-println-string)) + ;; (pop (const 1)) + + ;; it was found in a specific heap, this is most likely a real pointer. + ;; Look up the heap index of the object. + ;; + ;; Based on the heap index, look up the offset of the given pointer in the heap page. + ;; if it is heap page + 1, then it is an object (1st word is the heap control word) + ;; 0. heap control word <-- heap page base + ;; 1. vtab pointer <-- pointer + ;; 2. GCDW + ;; 3+ body + ;; if it is heap page + 3, then it is an array + ;; 0. heap control word <-- heap page base + ;; 1. length + ;; 2. GCDW + ;; 3+ body <-- pointer + ;; + ;; + ;; + ;; Right now the GC module must be aware of the heap layout, in + ;; order to figure out what offset a pointer is from the page + ;; it is contained in (so that in turn the GC will know whether + ;; the object is an array or an object). That should be + ;; modified, so that instead the GC will only need to look in a + ;; known location relative to the object pointer in order to + ;; find the GCDW. + ;; + ;; Sweep should be modularized to be a heap responsibility, + ;; because that sweep operation is dependent on heap layout. + ;; Sweep also clears the GCDW mark bit off of every object. + ;; The heap will have to know where to find the GCDW relative + ;; to the start of its page. + + ;; subtract the pointer from the heap base to get the offset in 'cell' units + (assign (temp base) (op load-array) (temp heap) (symconst heap:base)) + (assign (temp cell-offset) (op sub) (arg 0) (temp base)) + + ;; next figure out the pointer's offset from the base of the heap in 'word' units + (assign (temp word-offset) (op bit-rshift) (temp cell-offset) (symconst shift-cells-per-word)) + + ;; next figure out how many words there are in a page. Compute the 'modulus'. + (assign (temp mask-words-per-page) (op load-array) (temp heap) (symconst heap:mask-words-per-page)) + (assign (temp word-offset-mask) (op bit-and) (temp word-offset) (temp mask-words-per-page)) + + ;; finally, account for the heap-specific offset relative to the start of that heap page. + (assign (temp heap-object-offset) (op load-array) (temp heap) (symconst heap:object-offset)) + (assign (temp word-offset-mask) (op sub) (temp word-offset-mask) (temp heap-object-offset)) + +; ;; begin DEBUG +; (perform (op debug-out) (const "gc-mark-pointer; offset=") (temp word-offset-mask)) +; ;; end DEBUG + + (assign (temp offset-1) (op sub) (temp word-offset-mask) (const 0)) + (branch-nonzero (label gc-mark-pointer/test3) (temp offset-1)) + + ;; It is possible that this might be a non-aliased pointer to + ;; an array instead of a pointer to a class instance. We test + ;; that here. Notice that in this case, the GCDW will always + ;; be located at an offset of 1 from the non-aliased pointer. + ;; + ;; This code is only necessary when marking root pointers in + ;; the stack as used by the heap/GC code. This case should not + ;; turn up in user code whatsoever. We should always get the + ;; aliased array pointer from user code. But it's possible + ;; that there will be a non-aliased pointer sitting around in + ;; the stack from a previous GC or heap operation. So this + ;; code still needs to run all the time. + ;; + (assign (temp gcdw) (op load-array) (arg 0) (const 1)) + + ;; (push (const #xdeadc0db)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp gcdw)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + (assign (temp array-mask-result) + (op bit-and) (temp gcdw) (symconst gcdw:array-mask)) + (branch-nonzero (label gc-mark-pointer/mark-non-aliased-array) + (temp array-mask-result)) + + ;; Finally, check for non-class-instance objects, which use the + ;; "done" field of the GCDW to record a type ID integer. Such + ;; objects will have a non-zero "done" field and have no + ;; interior pointers so they can be marked inline. These forms + ;; of objects are typically objects allocated by the Scheme + ;; frontend of primitive type, such as characters or integers. + (assign (temp gcdw-done-field) + (op bit-and) (temp gcdw) (symconst gcdw:done-mask)) + (branch-zero (label gc-mark-pointer/class-instance) + (temp gcdw-done-field)) + + ;; Mark the primitive object. + (assign (temp gcdw) (op bit-or) (temp gcdw) (symconst gcdw:mark-mask)) + (perform (op store-array) (arg 0) (const 1) (temp gcdw)) + (goto (label gc-mark-pointer/end)) + + ;; Mark a class instance + (label gc-mark-pointer/class-instance) + ; check for 0 class pointer + (assign (temp gcdw) (op load-array) (arg 0) (const 0)) + (branch-zero (label gc-mark-pointer/end) (temp gcdw)) + ; actually mark the class instance + (push (arg 0)) + (perform (op call) (const gc-mark-class-instance)) + (goto (label gc-mark-pointer/end)) + + ;; Mark an aliased array pointer + (label gc-mark-pointer/mark-non-aliased-array) + (assign (temp aliased-array) (op add-pointer) (arg 0) (const 2)) + (push (temp aliased-array)) + (perform (op call) (const gc-mark-array)) + (goto (label gc-mark-pointer/end)) + + ;; One final check for a valid array pointer ... + (label gc-mark-pointer/test3) + + (assign (temp offset-3) (op sub) (temp word-offset-mask) (const 2)) + (branch-nonzero (label gc-mark-pointer/end) (temp offset-3)) + + ;; ... And finally mark the array pointer. + ;; (push (const #xdeadc0df)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp offset-3)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + (push (arg 0)) + (perform (op call) (const gc-mark-array)) + + (label gc-mark-pointer/end) + (perform (op pop-frame)) + (return (const 1)))) diff --git a/src/rtl/gc-stack.sasm b/src/rtl/gc-stack.sasm new file mode 100644 index 0000000..961cb0b --- /dev/null +++ b/src/rtl/gc-stack.sasm @@ -0,0 +1,60 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(export gc-mark-stack-roots) + +(function + (name gc-mark-stack-roots) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + +; ;; begin DEBUG +; (assign (reg accum) (label gc-debug-message-2)) +; (push (reg accum)) +; (perform (op call) (const mj-system-out-println-string)) +; (pop (const 1)) +; (push (sys stack-pointer)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; (assign (reg accum) (op load-array) (const gc-root-stack-limit) (const 0)) +; (push (reg accum)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; ;; end DEBUG + +; We used to use the current stack pointer as the base of the stack, but switched to +; using gc-stack-root-base as set on entry to malloc so that we would not look through +; the local variables of the heap/GC code itself when marking roots. +; (assign (temp stack-base) (sys stack-pointer)) + (assign (temp stack-base) (op load-array) (const gc-root-stack-base) (const 0)) + (assign (temp stack-limit) (op load-array) (const gc-root-stack-limit) (const 0)) + + (perform (op call) (const mm-heap-global-base)) + (perform (op store-array) (const gc-heap-base) (const 0) (reg accum)) + + (perform (op call) (const mm-heap-global-limit)) + (perform (op store-array) (const gc-heap-limit) (const 0) (reg accum)) + + (label gc-mark-stack-roots/begin) + (assign (temp test) (op less-than) (temp stack-base) (temp stack-limit)) + (branch-zero (label gc-mark-stack-roots/end) (temp test)) + +; ;; begin DEBUG +; (perform (op debug-out) (const "checking stack pointer ") (temp stack-base) (const " ") +; (result (op load-array) (temp stack-base) (const 0))) +; ;; end DEBUG + + (assign (temp ptr) (op load-array) (temp stack-base) (const 0)) + (push (temp ptr)) + (perform (op call) (const rtl-gc-mark-pointer)) + (pop (const 1)) + + (assign (temp stack-base) (op add-pointer) (temp stack-base) (const 1)) + (goto (label gc-mark-stack-roots/begin)) + + (label gc-mark-stack-roots/end) + (perform (op pop-frame)) + (return (const 0)))) + diff --git a/src/rtl/gc-sweep.sasm b/src/rtl/gc-sweep.sasm new file mode 100644 index 0000000..9175f36 --- /dev/null +++ b/src/rtl/gc-sweep.sasm @@ -0,0 +1,36 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(export gc-sweep) + +(function + (name gc-sweep) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp heap) (op load-array) (const root-heap-pointer) (const 0)) + + (label gc-sweep/begin) + (branch-zero (label gc-sweep/end) (temp heap)) + +; ;; begin DEBUG +; (assign (reg accum) (label gc-debug-message-4)) +; (push (reg accum)) +; (perform (op call) (const mj-system-out-println-string)) +; (pop (const 1)) +; (push (temp heap)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; ;; end DEBUG + + (push (temp heap)) + (perform (op call) (const mm-heap-sweep-area)) + + (assign (temp heap) (op load-array) (temp heap) (symconst heap:next)) + (goto (label gc-sweep/begin)) + + (label gc-sweep/end) + (perform (op pop-frame)) + (return (const 0)))) diff --git a/src/rtl/gc-wrapper.sasm b/src/rtl/gc-wrapper.sasm new file mode 100644 index 0000000..1eae127 --- /dev/null +++ b/src/rtl/gc-wrapper.sasm @@ -0,0 +1,97 @@ +(include "mm-param.sasm") +(include "gc-defines.sasm") +(include "gc-externs.sasm") + +(extern gc-invoke) +(extern gc-mark-stack-roots) +(extern gc-mark-memory-range) +(extern gc-sweep) + +(export c-gc-invoke) +(export c-gc-mark-stack-roots) +(export c-gc-mark-memory-range) +(export c-gc-sweep) + +;; wrappers to call from C + +(function (name c-gc-invoke) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (perform (op call) (const gc-invoke)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) + +(function (name c-gc-mark-stack-roots) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (perform (op call) (const gc-mark-stack-roots)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) + +(function (name c-gc-mark-memory-range) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const gc-mark-memory-range)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) + +(function (name c-gc-sweep) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (perform (op call) (const gc-sweep)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) diff --git a/src/rtl/gc.sasm b/src/rtl/gc.sasm new file mode 100644 index 0000000..3feb4fc --- /dev/null +++ b/src/rtl/gc.sasm @@ -0,0 +1,96 @@ +;; gc.sasm +;; Garbage collection routines + +;; Garbage Collection Descriptor Word: GCDW +;; +;; DONE - 16 bits, used for pointer reversal DFS (i.e. no class can have +;; more than 65535 members) +;; *NOTE* Also used for type tag, see below. *NOTE* +;; MARK - 1 bit, flag used in mark & sweep +;; LEAF - 1 bit, flag used to denote that the class or array has no child +;; pointers +;; ARRAY - 1 bit, used to denote that the object is an array and not a class +;; instance object +;; GCE - 1 bit, "garbage collection enable"; any objects not marked with +;; this bit are considered to be explicitly managed with malloc/free +;; +;; +;; CLASS INSTANCE OBJECT LAYOUT: +;; +;; +-----+-----+-----+- +;; | CP | GCDW| M0 | ... +;; +-----+-----+-----+- +;; +;; CP - class descriptor pointer +;; GCDW - garbage collection descriptor word +;; M0 - member #0 +;; +;; CLASS DESCRIPTOR OBJECT LAYOUT: +;; +;; +-----+-----+-----+- +;; | NM | F0 | F1 | ... +;; +-----+-----+-----+- +;; +;; NM - number of instance members +;; F0 - pointer to method 0 +;; F1 - pointer to method 1 +;; +;; ARRAY OBJECT LAYOUT: +;; +;; +-----+-----+-----+- +;; | NW | GCDW| IDX0| ... +;; +-----+-----+-----+- +;; +;; NW - number of words in the array, not counting NW or GCDW +;; GCDW - garbage collection descriptor word +;; IDX0 - index #0 + +;; Garbage Collection Algorithm: mark and sweep, with pointer reversal +;; +;; A simple, non-incremental, non-concurrent, mark&sweep algorithm is +;; employed. In the event of a malloc() failure, the GC module is +;; invoked. +;; +;; The GC module will traverse the entire current call-stack contents +;; looking for heap pointers; these will become the GC root pointers. +;; Only the stack needs to be traversed; no registers are used as GC +;; roots. This is because all registers are treated as caller-save by +;; this compiler and runtime system. Therefore CPU registers are not +;; considered GC roots. All GC roots will be found in either global +;; variables or in the stack. +;; +;; For each heap pointer found in the call stack, the GC mark routine +;; is invoked. This routine performs a DFS using the pointer-reversal +;; technique. The low 16 bits of the GCDW are used for the "done" +;; record, to know how many fields of the current object have been +;; marked. This field is used to implement the "pointer reversal" technique +;; for walking GC-managed objects during the mark-and-sweep phase. This +;; clever, textbook technique is used to eliminate the need for a deep call +;; stack that is usually required by a straightforward recursive walk +;; algorithm. *NOTE* Currently, this algorithm is planned for implementation +;; but is not currently used. Instead, the "DONE" field is used as a type +;; tag field by the Scheme compiler frontend. *NOTE* +;; +;; The sweep phase traverses the entire heap, reclaiming objects that +;; are not marked and un-marking any objects that are marked, for the +;; next traversal. +;; +;; The heap (defined in heap.sasm) has special properties that make it +;; easy and relatively precise to determine if a given integer value +;; is indeed a heap pointer. First, the pointer must fall within the +;; global bounds of the base of the lowest heap area and the limit of +;; the highest heap area. If that check passes, it must fall inside +;; the limits of one specific heap area. After that check passes, the +;; base pointer for the heap is subtracted, and the result must be an +;; integer multiple of the WORDS-PER-PAGE heap constant. If all of +;; these checks pass, the pointer is indeed a genuine heap pointer for +;; all intents and purposes. Care must be taken with array pointers +;; because they will be aliased; pointing two words ahead of the correct +;; heap pointer, and this will be a special case of the check above. +;; + +(export gc-heap-base) +(export gc-heap-limit) +(global gc-heap-base (const 0)) +(global gc-heap-limit (const 0)) + diff --git a/src/rtl/gctest.sasm b/src/rtl/gctest.sasm new file mode 100644 index 0000000..d890d1e --- /dev/null +++ b/src/rtl/gctest.sasm @@ -0,0 +1,43 @@ +;; gctest.sasm +;; Test app for the gc module + +(extern mm-heap-add-area) +(extern gc-mark-stack-roots) + +(entry gc-test-main) + +(class + (const 30)) + +(function + (name gc-test-main) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (const 56320)) ;; statically configured pointers into machine2 RAM + (push (const 9216)) + (perform (op call) (const mm-heap-add-area)) + + (perform (op call) (const gc-mark-stack-roots)) + + (push (const 32)) + (perform (op call) (const cp-rtl-malloc)) + (perform (op store-array) (reg accum) (const 0) (label )) + (assign (temp my-object) (reg accum)) + (push (temp my-object)) + (perform (op call) (const gc-mark-pointer)) + + (push (const 32)) + (perform (op call) (const cp-rtl-array-malloc)) + (perform (op store-array) (reg accum) (const 10) (temp my-object)) + (perform (op store-array) (temp my-object) (const 5) (reg accum)) + (push (reg accum)) + (perform (op call) (const gc-mark-pointer)) + + (perform (op call) (const gc-sweep)) + (perform (op call) (const gc-sweep)) + (perform (op call) (const gc-sweep)) + + (perform (op pop-frame)) + (return (const 0)))) diff --git a/src/rtl/get-percents.scm b/src/rtl/get-percents.scm new file mode 100644 index 0000000..3114ed2 --- /dev/null +++ b/src/rtl/get-percents.scm @@ -0,0 +1,26 @@ +;; get-percents.scm +;; Reads in the specified source code file and displays a list of all +;; unique %-prefixed commands referenced therein. + +(define print-percents + (let ((seen '())) + (lambda (obj) + (cond ((and (symbol? obj) + (not (member obj seen)) + (char=? #\% (string-ref (symbol->string obj) 0))) + (set! seen (cons obj seen)) + (write obj) + (newline)) + ((pair? obj) + (print-percents (car obj)) + (print-percents (cdr obj))))))) + +(if (not (= (vector-length *argv*) 2)) + (error "usage get-percents ")) + +(let ((file (open-input-file (vector-ref *argv* 1)))) + (let loop ((obj (read file))) + (if (eof-object? obj) + 'done + (begin (print-percents obj) + (loop (read file)))))) diff --git a/src/rtl/heap.sasm b/src/rtl/heap.sasm new file mode 100644 index 0000000..1b929a9 --- /dev/null +++ b/src/rtl/heap.sasm @@ -0,0 +1,466 @@ +;; heap.sasm +;; malloc and free, based on a paged-heap design and implemented in SASM + +(export mm-malloc) +(export mm-free) +(export mm-fixed-malloc) +(export mm-heap-global-base) +(export mm-heap-global-limit) +(export mm-heap-assoc) +(export mm-heap-sweep-area) +(export root-heap-pointer) + +(export c-mm-malloc) +(export c-mm-free) +(export c-mm-heap-add-area) +(export c-mm-heap-add-fixed-area) + +(global root-heap-pointer (const 0)) +(global root-fixed-heap-pointer (const 0)) + +(extern mm-var-heap-add-area) +(extern mm-var-heap-area-free) +(extern mm-var-heap-area-malloc) +(extern mm-var-heap-sweep-area) +(extern cp-mm-fixed-heap-area-init) +(extern cp-mm-fixed-heap-area-malloc) +(extern cp-mm-fixed-heap-area-free) +(extern cp-mm-fixed-heap-area-sweep) + + +(export mm-heap-insert-area-into-list) +(export mm-heap-add-area) +(export mm-heap-add-fixed-area) +(export mm-heap-area-malloc) +(export mm-heap-area-free) + +; (global heap-debug-message-1 (const "free pointer, searching heap:")) + +(include "mm-param.sasm") + +(function (name c-mm-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (push (arg 0)) + (perform (op call) (const mm-malloc)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) + +(function (name c-mm-free) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (push (arg 0)) + (perform (op call) (const mm-free)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) + +(function (name c-mm-heap-add-area) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const mm-heap-add-area)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) + +(function (name c-mm-heap-add-fixed-area) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg operand)) + (save (reg index)) + (save (reg link)) + (save (reg pointer)) + + (push (arg 2)) + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const mm-heap-add-fixed-area)) + + (restore (reg pointer)) + (restore (reg link)) + (restore (reg index)) + (restore (reg operand)) + + (perform (op pop-frame)) + (return))) + +(function (name mm-heap-insert-area-into-list) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp heap) (arg 0)) + (assign (temp tail) (op load-array) (const root-heap-pointer) (const 0)) + (perform (op store-array) (temp heap) (symconst heap:next) (temp tail)) + (perform (op store-array) (const root-heap-pointer) (const 0) (temp heap)) + + (assign (reg accum) (arg 0)) + (perform (op pop-frame)) + (return (const 1)))) + +(function (name mm-heap-add-area) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-add-area)) + + (assign (temp heap) (reg accum)) + (push (temp heap)) + (perform (op call) (const mm-heap-insert-area-into-list)) + + (assign (reg accum) (temp heap)) + (perform (op pop-frame)) + (return (const 2)))) + +(function (name mm-heap-add-fixed-area) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 2)) + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-init)) + + (assign (temp heap) (arg 0)) + (assign (temp tail) (op load-array) (const root-heap-pointer) (const 0)) + (perform (op store-array) (temp heap) (symconst heap:next) (temp tail)) + (perform (op store-array) (const root-heap-pointer) (const 0) (temp heap)) + + (assign (temp heap) (arg 0)) + (assign (temp tail) (op load-array) (const root-fixed-heap-pointer) (const 0)) + (perform (op store-array) (temp heap) (symconst fixed-heap:next-fixed-heap) (temp tail)) + (perform (op store-array) (const root-fixed-heap-pointer) (const 0) (temp heap)) + (perform (op pop-frame)) + (return (const 3)))) + +(function + (name mm-heap-global-base) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 1)) + + (assign (temp base) (const 0)) + (assign (temp heap) (op load-array) (const root-heap-pointer) (const 0)) + + (branch-zero (label mm-heap-global-base/end) (temp heap)) + (assign (temp base) (op load-array) (temp heap) (symconst heap:base)) + (assign (temp heap) (op load-array) (temp heap) (symconst heap:next)) + + (label mm-heap-global-base/start) + (branch-zero (label mm-heap-global-base/end) (temp heap)) + (assign (temp heap-base) (op load-array) (temp heap) (symconst heap:base)) + (assign (temp test) (op less-than) (temp heap-base) (temp base)) + (branch-zero (label mm-heap-global-base/next) (temp test)) + (assign (temp base) (temp heap-base)) + (label mm-heap-global-base/next) + (assign (temp heap) (op load-array) (temp heap) (symconst heap:next)) + (goto (label mm-heap-global-base/start)) + + (label mm-heap-global-base/end) + (assign (reg accum) (temp base)) + (perform (op pop-frame)) + (return (const 0)))) + +(function + (name mm-heap-global-limit) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 1)) + + (assign (temp limit) (const 0)) + (assign (temp heap) (op load-array) (const root-heap-pointer) (const 0)) + + (label mm-heap-global-limit/start) + (branch-zero (label mm-heap-global-limit/end) (temp heap)) + (assign (temp heap-limit) (op load-array) (temp heap) (symconst heap:limit)) + + (assign (temp test) (op less-than) (temp limit) (temp heap-limit)) + (branch-zero (label mm-heap-global-limit/next) (temp test)) + (assign (temp limit) (temp heap-limit)) + (label mm-heap-global-limit/next) + (assign (temp heap) (op load-array) (temp heap) (symconst heap:next)) + (goto (label mm-heap-global-limit/start)) + + (label mm-heap-global-limit/end) + (assign (reg accum) (temp limit)) + (perform (op pop-frame)) + (return (const 0)))) + +(function (name mm-heap-assoc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp result-heap) (const 0)) + (assign (temp heap) (op load-array) (const root-heap-pointer) (const 0)) + + (label mm-heap-assoc/start) + (branch-zero (label mm-heap-assoc/end) (temp heap)) + (assign (temp base) (op load-array) (temp heap) (symconst heap:base)) + (assign (temp limit) (op load-array) (temp heap) (symconst heap:limit)) + + (assign (temp test) (op less-than-or-equal) (temp base) (arg 0)) + (branch-zero (label mm-heap-assoc/next) (temp test)) + + (assign (temp test) (op less-than) (arg 0) (temp limit)) + (branch-zero (label mm-heap-assoc/next) (temp test)) + + (assign (temp result-heap) (temp heap)) + (goto (label mm-heap-assoc/end)) + + (label mm-heap-assoc/next) + (assign (temp heap) (op load-array) (temp heap) (symconst heap:next)) + (goto (label mm-heap-assoc/start)) + + (label mm-heap-assoc/end) + (assign (reg accum) (temp result-heap)) + (perform (op pop-frame)) + (return (const 1)))) + +(function (name mm-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp result) (const 0)) + (assign (temp heap) (op load-array) (const root-heap-pointer) (const 0)) + + (label mm-malloc/start) + (branch-zero (label mm-malloc/end) (temp heap)) + + (push (arg 0)) + (push (temp heap)) + (perform (op call) (const mm-heap-area-malloc)) + (assign (temp result) (reg accum)) + (branch-nonzero (label mm-malloc/end) (temp result)) + + (assign (temp heap) (op load-array) (temp heap) (symconst heap:next)) + (goto (label mm-malloc/start)) + + (label mm-malloc/end) + (assign (reg accum) (temp result)) + (perform (op pop-frame)) + (return (const 1)))) + +(function (name mm-fixed-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp result) (const 0)) + (assign (temp heap) (op load-array) (const root-fixed-heap-pointer) (const 0)) + + (label mm-fixed-malloc/start) + (branch-zero (label mm-fixed-malloc/end) (temp heap)) + + (push (arg 0)) + (push (temp heap)) + (perform (op call) (const mm-heap-area-malloc)) + (assign (temp result) (reg accum)) + (branch-nonzero (label mm-fixed-malloc/end) (temp result)) + + (assign (temp heap) (op load-array) (temp heap) (symconst fixed-heap:next-fixed-heap)) + (goto (label mm-fixed-malloc/start)) + + (label mm-fixed-malloc/end) + (assign (reg accum) (temp result)) + (perform (op pop-frame)) + (return (const 1)))) + +(function (name mm-heap-area-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; check to see what kind of heap this is. + (assign (temp type) (op load-array) (arg 0) (symconst heap:type)) + (assign (temp test) (op equal-to) (temp type) (symconst heap-type:fixed-alloc)) + (branch-nonzero (label mm-heap-area-malloc/fixed) (temp test)) + + ;; variable-allocation heap. + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-area-malloc)) + (goto (label mm-heap-area-malloc/done)) + + (label mm-heap-area-malloc/fixed) + ;; fixed-heap. Check to make sure the chunk size is big enough. + (assign (temp block) (op load-array) (arg 0) (symconst heap:words-per-page)) + (assign (temp test) (op less-than-or-equal) (arg 1) (temp block)) + (branch-zero (label mm-heap-area-malloc/fail) (temp test)) + + ;; it's big enough. call malloc and the we're done. + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-malloc)) + (goto (label mm-heap-area-malloc/done)) + + ;; the fixed heap's chunk size is not big enough. + (label mm-heap-area-malloc/fail) + (assign (reg accum) (const 0)) + + ;; return + (label mm-heap-area-malloc/done) + (perform (op pop-frame)) + (return (const 2)))) + +(function (name mm-free) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp heap) (op load-array) (const root-heap-pointer) (const 0)) + + (label mm-free/start) + (assign (temp base) (op load-array) (temp heap) (symconst heap:base)) + (assign (temp limit) (op add) (temp base) (symconst heap:limit)) + +; ;; begin DEBUG +; (assign (reg accum) (label heap-debug-message-1)) +; (push (reg accum)) +; (perform (op call) (const mj-system-out-println-string)) +; (pop (const 1)) +; (push (arg 0)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; (push (temp base)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; (push (temp limit)) +; (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) +; ;; end DEBUG + +; ;; begin DEBUG +; (push (const "free pointer, searching heap:")) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (arg 0)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp base)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp pages)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp limit)) +; (perform (op call) (const cp-mj-system-out-println)) +; ;; end DEBUG + + (assign (temp test) (op less-than-or-equal) (temp base) (arg 0)) + (branch-zero (label mm-free/next) (temp test)) + + (assign (temp test) (op less-than) (arg 0) (temp limit)) + (branch-zero (label mm-free/next) (temp test)) + +; ;; begin DEBUG +; (push (const "free pointer, *** found heap ***")) +; (perform (op call) (const cp-mj-system-out-println)) +; ;; end DEBUG + + (push (arg 0)) + (push (temp heap)) + (perform (op call) (const mm-heap-area-free)) + (goto (label mm-free/end)) + + (label mm-free/next) + (assign (temp heap) (op load-array) (temp heap) (symconst heap:next)) + (goto (label mm-free/start)) + + (label mm-free/end) + (perform (op pop-frame)) + (return (const 1)))) + +;; void mm_heap_area_free( heap* h, void* ptr ); +(function (name mm-heap-area-free) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 1)) + + ;; check to see if this is a fixed or variable allocation heap. + (assign (temp type) (op load-array) (arg 0) (symconst heap:type)) + (assign (temp test) (op equal-to) (temp type) (symconst heap-type:fixed-alloc)) + (branch-nonzero (label mm-heap-area-free/fixed) (temp test)) + + ;; it's variable. call free. + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-area-free)) + (goto (label mm-heap-area-free/done)) + + ;; it's fixed. call free. + (label mm-heap-area-free/fixed) + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-free)) + + ;; return + (label mm-heap-area-free/done) + (perform (op pop-frame)) + (return (const 2)))) + +(function (name mm-heap-sweep-area) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 1)) + + ;; check to see if this is a fixed or variable allocation heap. + (assign (temp type) (op load-array) (arg 0) (symconst heap:type)) + (assign (temp test) (op equal-to) (temp type) (symconst heap-type:fixed-alloc)) + (branch-nonzero (label mm-heap-sweep-area/fixed) (temp test)) + + ;; variable. call sweep. + (push (arg 0)) + (perform (op call) (const mm-var-heap-sweep-area)) + (goto (label mm-heap-sweep-area/done)) + + ;; fixed. call sweep. + (label mm-heap-sweep-area/fixed) + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-sweep)) + + ;; return. + (label mm-heap-sweep-area/done) + (perform (op pop-frame)) + (return (const 1)))) diff --git a/src/rtl/heapfixed-debug.sasm b/src/rtl/heapfixed-debug.sasm new file mode 100644 index 0000000..de03969 --- /dev/null +++ b/src/rtl/heapfixed-debug.sasm @@ -0,0 +1,352 @@ +;; rtl/heapfixed.sasm + +(include "mm-param.sasm") +(include "gc-defines.sasm") + +(export cp-mm-fixed-heap-area-malloc) +(export cp-mm-fixed-heap-area-free) +(export cp-mm-fixed-heap-area-init) +(export cp-mm-fixed-heap-area-sweep) +(export cp-mm-fixed-heap-area-check) +(extern c-fail-bad-heap-check) +(extern mj-system-out-println) + +(define-symconst + (fixed-heap:next-free-entry 0)) + +(global heap-check-count (const 0)) + +;; int cp_mm_fixed_heap_area_check( heap *h ); +(function (name cp-mm-fixed-heap-area-check) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp free-pages) (const 0)) + (assign (temp free-page) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + (label cp-mm-fixed-heap-area-check/start) + (branch-zero (label cp-mm-fixed-heap-area-check/done) (temp free-page)) + + (assign (temp free-pages) (op add) (temp free-pages) (const 1)) + (assign (reg accum) (temp free-page)) + (assign (temp magic) (op load-array) (reg accum) (const 2)) + (assign (temp check) (op equal-to) (temp magic) (const #xdeadca5e)) + (branch-nonzero (label cp-mm-fixed-heap-area-check/ok1) (temp check)) + + (push (const #x500005ad)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-page)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-pages)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp magic)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-check/ok1) + (assign (temp magic) (op load-array) (reg accum) (const 1)) + (assign (temp check1) (op equal-to) (temp magic) (const 9)) + ;(assign (temp check2) (op equal-to) (temp magic) (const #x10009)) + ;(assign (temp check) (op bit-or) (temp check1) (temp check2)) + (branch-nonzero (label cp-mm-fixed-heap-area-check/ok2) (temp check1)) + + (push (const #xdeadcad0)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-page)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-pages)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp magic)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-check/ok2) + (assign (temp free-page) (op load-array) (reg accum) (const 0)) + (goto (label cp-mm-fixed-heap-area-check/start)) + + (label cp-mm-fixed-heap-area-check/done) + + ;; (push (const #xd00df00d)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp free-pages)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (assign (reg accum) (op load-array) (const heap-check-count) (const 0)) + ;; (push (reg accum)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (assign (reg accum) (op load-array) (const heap-check-count) (const 0)) + ;; (assign (reg accum) (op add) (reg accum) (const 1)) + ;; (perform (op store-array) (const heap-check-count) (const 0) (reg accum)) + + (perform (op pop-frame)) + (return (const 1)))) + +;; int cp_mm_fixed_heap_area_malloc( heap *h ); +(function (name cp-mm-fixed-heap-area-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; debug - heap consistency check + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + + (assign (reg accum) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + (branch-zero (label cp-mm-fixed-heap-area-malloc/done) (reg accum)) + + (assign (temp magic) (op load-array) (reg accum) (const 2)) + (assign (temp check) (op equal-to) (temp magic) (const #xdeadca5e)) + (branch-nonzero (label cp-mm-fixed-heap-area-malloc/ok1) (temp check)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-malloc/ok1) + (assign (temp magic) (op load-array) (reg accum) (const 1)) + (assign (temp check) (op equal-to) (temp magic) (const 9)) + (branch-nonzero (label cp-mm-fixed-heap-area-malloc/ok2) (temp check)) + + (push (const #xdeadcade)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp magic)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-malloc/ok2) + (assign (temp next) (op load-array) (reg accum) (symconst fixed-heap:next-free-entry)) + (perform (op store-array) (arg 0) (symconst fixed-heap:free-list) (temp next)) + + (label cp-mm-fixed-heap-area-malloc/done) + + ;; debug - heap consistency check + (save (reg accum)) + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + (restore (reg accum)) + + (perform (op pop-frame)) + (return (const 1)))) + +;; void cp_mm_fixed_heap_area_free( heap *h, void *ptr ); +(function (name cp-mm-fixed-heap-area-free) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;(push (arg 0)) + ;(perform (op call) (const cp-mm-fixed-heap-area-check)) + +; ;; begin debug +; (perform (op debug-out) (const "heap-free: ") (arg 0) (const " ") (arg 1)) + ; ;; end debug + + (perform (op store-array) (arg 1) (const 1) (const 9)) + (perform (op store-array) (arg 1) (const 2) (const #xdeadca5e)) + + (assign (reg accum) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + (perform (op store-array) (arg 1) (symconst fixed-heap:next-free-entry) (reg accum)) + (perform (op store-array) (arg 0) (symconst fixed-heap:free-list) (arg 1)) + + ;(push (arg 0)) + ;(perform (op call) (const cp-mm-fixed-heap-area-check)) + + (perform (op pop-frame)) + (return (const 2)))) + +;;int cp_mm_fixed_heap_area_init( heap *h, size_t chunk, size_t total ) +(function (name cp-mm-fixed-heap-area-init) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp temp-ptr) (op add-pointer) (arg 0) (symconst sizeof:fixed-heap)) + (assign (temp bytes-per-chunk) (op bit-lshift) (arg 1) (symconst shift-cells-per-word)) + (assign (temp total-bytes) (arg 2)) + (assign (temp end-buf) (op add) (arg 0) (temp total-bytes)) + + (assign (temp shift-words-per-page) (const 0)) + (assign (reg operand) (arg 1)) + (label cp-mm-fixed-heap-area-init/swpp) + (assign (temp test) (op equal-to) (reg operand) (const 1)) + (branch-nonzero (label cp-mm-fixed-heap-area-init/swpp-done) + (temp test)) + (assign (reg operand) (op bit-rshift) (reg operand) (const 1)) + (assign (temp shift-words-per-page) (op add) (temp shift-words-per-page) (const 1)) + (goto (label cp-mm-fixed-heap-area-init/swpp)) + (label cp-mm-fixed-heap-area-init/swpp-done) + + (assign (temp mask-words-per-page) (op sub) (arg 1) (const 1)) + + (perform (op store-array) (arg 0) (symconst heap:base) (temp temp-ptr)) + (perform (op store-array) (arg 0) (symconst heap:limit) (temp end-buf)) + (perform (op store-array) (arg 0) (symconst heap:object-offset) (const 0)) + (perform (op store-array) (arg 0) (symconst heap:words-per-page) (arg 1)) + (perform (op store-array) (arg 0) (symconst heap:shift-words-per-page) (temp shift-words-per-page)) + (perform (op store-array) (arg 0) (symconst heap:mask-words-per-page) (temp mask-words-per-page)) + (perform (op store-array) (arg 0) (symconst heap:next) (const 0)) + (perform (op store-array) (arg 0) (symconst heap:type) (symconst heap-type:fixed-alloc)) + (perform (op store-array) (arg 0) (symconst fixed-heap:free-list) (temp temp-ptr)) + (perform (op store-array) (arg 0) (symconst fixed-heap:next-fixed-heap) (const 0)) + + (assign (temp buffer) (temp temp-ptr)) + + (label cp-mm-fixed-heap-area-init/start) + (perform (op store-array) (temp buffer) (const 1) (const 9)) + (perform (op store-array) (temp buffer) (const 2) (const #xdeadca5e)) + (assign (temp next) (op add) (temp buffer) (temp bytes-per-chunk)) + (assign (temp nextnext) (op add) (temp next) (temp bytes-per-chunk)) + (assign (temp test) (op less-than) (temp next) (temp end-buf)) + (branch-zero (label cp-mm-fixed-heap-area-init/end) (temp test)) + (assign (temp test) (op less-than) (temp nextnext) (temp end-buf)) + (branch-zero (label cp-mm-fixed-heap-area-init/end) (temp test)) + (perform (op store-array) (temp buffer) (symconst fixed-heap:next-free-entry) (temp next)) + (assign (temp buffer) (temp next)) + (goto (label cp-mm-fixed-heap-area-init/start)) + + (label cp-mm-fixed-heap-area-init/end) + (perform (op store-array) (temp buffer) (symconst fixed-heap:next-free-entry) (const 0)) + + ;; debug - heap consistency check + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + + (perform (op pop-frame)) + (return (const 3)))) + +(function + (name cp-mm-fixed-heap-area-sweep) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; debug - heap consistency check + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + + ;; (push (const #x11111111)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; first walk through the free list and set the GCDW + (assign (temp free) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + + (label cp-mm-fixed-heap-area-sweep/free-list) + (branch-zero (label cp-mm-fixed-heap-area-sweep/free-marked) (temp free)) + (assign (reg accum) (op load-array) (temp free) (symconst gcdw:offset)) + (assign (reg accum) (op bit-or) (reg accum) (symconst gcdw:mark-mask)) + (perform (op store-array) (temp free) (symconst gcdw:offset) (reg accum)) + (assign (temp free) (op load-array) (temp free) (symconst fixed-heap:next-free-entry)) + (goto (label cp-mm-fixed-heap-area-sweep/free-list)) + (label cp-mm-fixed-heap-area-sweep/free-marked) + + ;; now walk through the heap and + ;; 1. free non-marked pages + ;; 2. un-mark marked pages + ;; + (assign (temp page) (op load-array) (arg 0) (symconst heap:base)) + (assign (temp block) (op load-array) (arg 0) (symconst heap:words-per-page)) + (assign (temp block-cells) (op bit-lshift) (temp block) (symconst shift-cells-per-word)) + (assign (temp limit) (op load-array) (arg 0) (symconst heap:limit)) + + (label cp-mm-fixed-area-sweep/sweep) + + ;; if we've run up to or over the limit, then we're done + (assign (temp test) (op less-than) (temp page) (temp limit)) + (branch-zero (label cp-mm-fixed-area-sweep/sweep-done) (temp test)) + + ;; check the GCDW; is this page in use or not? + (assign (temp gcdw) (op load-array) (temp page) (symconst gcdw:offset)) + (assign (temp test) (op bit-and) (temp gcdw) (symconst gcdw:mark-mask)) + (branch-nonzero (label cp-mm-fixed-area-sweep/page-in-use) (temp test)) + + + ;; debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; (push (const #xdead0001)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp page)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp gcdw)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp test)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + ;; end debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ;; the page is not in use so free it. + (push (temp page)) + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-free)) + (goto (label cp-mm-fixed-area-sweep/next-page)) + + ;; the page is in use, so clear the GCDW. + (label cp-mm-fixed-area-sweep/page-in-use) + (assign (temp unmark-mask) (op bit-not) (symconst gcdw:mark-mask)) + (assign (temp unmarked) (op bit-and) (temp gcdw) (temp unmark-mask)) + + ;; debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; (push (const #xdeadcadf)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp page)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp gcdw)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp test)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp unmarked)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + ;; end debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (perform (op store-array) (temp page) (symconst gcdw:offset) (temp unmarked)) + + ;; loop to the next page + (label cp-mm-fixed-area-sweep/next-page) + (assign (temp page) (op add) (temp page) (temp block-cells)) + (goto (label cp-mm-fixed-area-sweep/sweep)) + + (label cp-mm-fixed-area-sweep/sweep-done) + + ;; debug - heap consistency check + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + + (perform (op pop-frame)) + (return (const 1)))) diff --git a/src/rtl/heapfixed.sasm b/src/rtl/heapfixed.sasm new file mode 100644 index 0000000..bb5dc8a --- /dev/null +++ b/src/rtl/heapfixed.sasm @@ -0,0 +1,352 @@ +;; rtl/heapfixed.sasm + +(include "mm-param.sasm") +(include "gc-defines.sasm") + +(export cp-mm-fixed-heap-area-malloc) +(export cp-mm-fixed-heap-area-free) +(export cp-mm-fixed-heap-area-init) +(export cp-mm-fixed-heap-area-sweep) +(export cp-mm-fixed-heap-area-check) +(extern c-fail-bad-heap-check) +(extern mj-system-out-println) + +(define-symconst + (fixed-heap:next-free-entry 0)) + +(global heap-check-count (const 0)) + +;; int cp_mm_fixed_heap_area_check( heap *h ); +(function (name cp-mm-fixed-heap-area-check) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp free-pages) (const 0)) + (assign (temp free-page) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + (label cp-mm-fixed-heap-area-check/start) + (branch-zero (label cp-mm-fixed-heap-area-check/done) (temp free-page)) + + (assign (temp free-pages) (op add) (temp free-pages) (const 1)) + (assign (reg accum) (temp free-page)) + (assign (temp magic) (op load-array) (reg accum) (const 2)) + (assign (temp check) (op equal-to) (temp magic) (const #xdeadca5e)) + (branch-nonzero (label cp-mm-fixed-heap-area-check/ok1) (temp check)) + + (push (const #x500005ad)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-page)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-pages)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp magic)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-check/ok1) + (assign (temp magic) (op load-array) (reg accum) (const 1)) + (assign (temp check1) (op equal-to) (temp magic) (const 99)) + ;(assign (temp check2) (op equal-to) (temp magic) (const #x10009)) + ;(assign (temp check) (op bit-or) (temp check1) (temp check2)) + (branch-nonzero (label cp-mm-fixed-heap-area-check/ok2) (temp check1)) + + (push (const #xdeadcad0)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-page)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp free-pages)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp magic)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-check/ok2) + (assign (temp free-page) (op load-array) (reg accum) (const 0)) + (goto (label cp-mm-fixed-heap-area-check/start)) + + (label cp-mm-fixed-heap-area-check/done) + + ;; (push (const #xd00df00d)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp free-pages)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (assign (reg accum) (op load-array) (const heap-check-count) (const 0)) + ;; (push (reg accum)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (assign (reg accum) (op load-array) (const heap-check-count) (const 0)) + ;; (assign (reg accum) (op add) (reg accum) (const 1)) + ;; (perform (op store-array) (const heap-check-count) (const 0) (reg accum)) + + (perform (op pop-frame)) + (return (const 1)))) + +;; int cp_mm_fixed_heap_area_malloc( heap *h ); +(function (name cp-mm-fixed-heap-area-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; ;; debug - heap consistency check (currently disabled) + ;; (push (arg 0)) + ;; (perform (op call) (const cp-mm-fixed-heap-area-check)) + + (assign (reg accum) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + (branch-zero (label cp-mm-fixed-heap-area-malloc/done) (reg accum)) + + (assign (temp magic) (op load-array) (reg accum) (const 2)) + (assign (temp check) (op equal-to) (temp magic) (const #xdeadca5e)) + (branch-nonzero (label cp-mm-fixed-heap-area-malloc/ok1) (temp check)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-malloc/ok1) + (assign (temp magic) (op load-array) (reg accum) (const 1)) + (assign (temp check) (op equal-to) (temp magic) (const 99)) + (branch-nonzero (label cp-mm-fixed-heap-area-malloc/ok2) (temp check)) + + (push (const #xdeadcade)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (push (temp magic)) + (perform (op call) (const mj-system-out-println)) + (pop (const 1)) + + (perform (op call) (const c-fail-bad-heap-check)) + + (label cp-mm-fixed-heap-area-malloc/ok2) + (assign (temp next) (op load-array) (reg accum) (symconst fixed-heap:next-free-entry)) + (perform (op store-array) (arg 0) (symconst fixed-heap:free-list) (temp next)) + + (label cp-mm-fixed-heap-area-malloc/done) + + ;; ;; debug - heap consistency check (currently disabled) + ;; (save (reg accum)) + ;; (push (arg 0)) + ;; (perform (op call) (const cp-mm-fixed-heap-area-check)) + ;; (restore (reg accum)) + + (perform (op pop-frame)) + (return (const 1)))) + +;; void cp_mm_fixed_heap_area_free( heap *h, void *ptr ); +(function (name cp-mm-fixed-heap-area-free) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;(push (arg 0)) + ;(perform (op call) (const cp-mm-fixed-heap-area-check)) + +; ;; begin debug +; (perform (op debug-out) (const "heap-free: ") (arg 0) (const " ") (arg 1)) + ; ;; end debug + + (perform (op store-array) (arg 1) (const 1) (const 99)) + (perform (op store-array) (arg 1) (const 2) (const #xdeadca5e)) + + (assign (reg accum) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + (perform (op store-array) (arg 1) (symconst fixed-heap:next-free-entry) (reg accum)) + (perform (op store-array) (arg 0) (symconst fixed-heap:free-list) (arg 1)) + + ;(push (arg 0)) + ;(perform (op call) (const cp-mm-fixed-heap-area-check)) + + (perform (op pop-frame)) + (return (const 2)))) + +;;int cp_mm_fixed_heap_area_init( heap *h, size_t chunk, size_t total ) +(function (name cp-mm-fixed-heap-area-init) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp temp-ptr) (op add-pointer) (arg 0) (symconst sizeof:fixed-heap)) + (assign (temp bytes-per-chunk) (op bit-lshift) (arg 1) (symconst shift-cells-per-word)) + (assign (temp total-bytes) (arg 2)) + (assign (temp end-buf) (op add) (arg 0) (temp total-bytes)) + + (assign (temp shift-words-per-page) (const 0)) + (assign (reg operand) (arg 1)) + (label cp-mm-fixed-heap-area-init/swpp) + (assign (temp test) (op equal-to) (reg operand) (const 1)) + (branch-nonzero (label cp-mm-fixed-heap-area-init/swpp-done) + (temp test)) + (assign (reg operand) (op bit-rshift) (reg operand) (const 1)) + (assign (temp shift-words-per-page) (op add) (temp shift-words-per-page) (const 1)) + (goto (label cp-mm-fixed-heap-area-init/swpp)) + (label cp-mm-fixed-heap-area-init/swpp-done) + + (assign (temp mask-words-per-page) (op sub) (arg 1) (const 1)) + + (perform (op store-array) (arg 0) (symconst heap:base) (temp temp-ptr)) + (perform (op store-array) (arg 0) (symconst heap:limit) (temp end-buf)) + (perform (op store-array) (arg 0) (symconst heap:object-offset) (const 0)) + (perform (op store-array) (arg 0) (symconst heap:words-per-page) (arg 1)) + (perform (op store-array) (arg 0) (symconst heap:shift-words-per-page) (temp shift-words-per-page)) + (perform (op store-array) (arg 0) (symconst heap:mask-words-per-page) (temp mask-words-per-page)) + (perform (op store-array) (arg 0) (symconst heap:next) (const 0)) + (perform (op store-array) (arg 0) (symconst heap:type) (symconst heap-type:fixed-alloc)) + (perform (op store-array) (arg 0) (symconst fixed-heap:free-list) (temp temp-ptr)) + (perform (op store-array) (arg 0) (symconst fixed-heap:next-fixed-heap) (const 0)) + + (assign (temp buffer) (temp temp-ptr)) + + (label cp-mm-fixed-heap-area-init/start) + (perform (op store-array) (temp buffer) (const 1) (const 99)) + (perform (op store-array) (temp buffer) (const 2) (const #xdeadca5e)) + (assign (temp next) (op add) (temp buffer) (temp bytes-per-chunk)) + (assign (temp nextnext) (op add) (temp next) (temp bytes-per-chunk)) + (assign (temp test) (op less-than) (temp next) (temp end-buf)) + (branch-zero (label cp-mm-fixed-heap-area-init/end) (temp test)) + (assign (temp test) (op less-than) (temp nextnext) (temp end-buf)) + (branch-zero (label cp-mm-fixed-heap-area-init/end) (temp test)) + (perform (op store-array) (temp buffer) (symconst fixed-heap:next-free-entry) (temp next)) + (assign (temp buffer) (temp next)) + (goto (label cp-mm-fixed-heap-area-init/start)) + + (label cp-mm-fixed-heap-area-init/end) + (perform (op store-array) (temp buffer) (symconst fixed-heap:next-free-entry) (const 0)) + + ;; debug - heap consistency check + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + + (perform (op pop-frame)) + (return (const 3)))) + +(function + (name cp-mm-fixed-heap-area-sweep) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; debug - heap consistency check + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + + ;; (push (const #x11111111)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; first walk through the free list and set the GCDW + (assign (temp free) (op load-array) (arg 0) (symconst fixed-heap:free-list)) + + (label cp-mm-fixed-heap-area-sweep/free-list) + (branch-zero (label cp-mm-fixed-heap-area-sweep/free-marked) (temp free)) + (assign (reg accum) (op load-array) (temp free) (symconst gcdw:offset)) + (assign (reg accum) (op bit-or) (reg accum) (symconst gcdw:mark-mask)) + (perform (op store-array) (temp free) (symconst gcdw:offset) (reg accum)) + (assign (temp free) (op load-array) (temp free) (symconst fixed-heap:next-free-entry)) + (goto (label cp-mm-fixed-heap-area-sweep/free-list)) + (label cp-mm-fixed-heap-area-sweep/free-marked) + + ;; now walk through the heap and + ;; 1. free non-marked pages + ;; 2. un-mark marked pages + ;; + (assign (temp page) (op load-array) (arg 0) (symconst heap:base)) + (assign (temp block) (op load-array) (arg 0) (symconst heap:words-per-page)) + (assign (temp block-cells) (op bit-lshift) (temp block) (symconst shift-cells-per-word)) + (assign (temp limit) (op load-array) (arg 0) (symconst heap:limit)) + + (label cp-mm-fixed-area-sweep/sweep) + + ;; if we've run up to or over the limit, then we're done + (assign (temp test) (op less-than) (temp page) (temp limit)) + (branch-zero (label cp-mm-fixed-area-sweep/sweep-done) (temp test)) + + ;; check the GCDW; is this page in use or not? + (assign (temp gcdw) (op load-array) (temp page) (symconst gcdw:offset)) + (assign (temp test) (op bit-and) (temp gcdw) (symconst gcdw:mark-mask)) + (branch-nonzero (label cp-mm-fixed-area-sweep/page-in-use) (temp test)) + + + ;; debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; (push (const #xdead0001)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp page)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp gcdw)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp test)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + ;; end debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ;; the page is not in use so free it. + (push (temp page)) + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-free)) + (goto (label cp-mm-fixed-area-sweep/next-page)) + + ;; the page is in use, so clear the GCDW. + (label cp-mm-fixed-area-sweep/page-in-use) + (assign (temp unmark-mask) (op bit-not) (symconst gcdw:mark-mask)) + (assign (temp unmarked) (op bit-and) (temp gcdw) (temp unmark-mask)) + + ;; debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; (push (const #xdeadcadf)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp page)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp gcdw)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp test)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + + ;; (push (temp unmarked)) + ;; (perform (op call) (const mj-system-out-println)) + ;; (pop (const 1)) + ;; end debug ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (perform (op store-array) (temp page) (symconst gcdw:offset) (temp unmarked)) + + ;; loop to the next page + (label cp-mm-fixed-area-sweep/next-page) + (assign (temp page) (op add) (temp page) (temp block-cells)) + (goto (label cp-mm-fixed-area-sweep/sweep)) + + (label cp-mm-fixed-area-sweep/sweep-done) + + ;; debug - heap consistency check + (push (arg 0)) + (perform (op call) (const cp-mm-fixed-heap-area-check)) + + (perform (op pop-frame)) + (return (const 1)))) diff --git a/src/rtl/heaptest.sasm b/src/rtl/heaptest.sasm new file mode 100644 index 0000000..dbdd3aa --- /dev/null +++ b/src/rtl/heaptest.sasm @@ -0,0 +1,208 @@ +;; heaptest.sasm +;; A heap test program, using the functions exported by heap.sasm + +(entry exercise-heap) + +;; (function (name heap-test-main) +;; (locals 0) +;; (body (perform (op push-frame)) +;; (perform (op reserve-locals) (const 0)) + +;; (push (const 56320)) ;; statically configured pointers into machine2 RAM +;; (push (const 9216)) +;; (perform (op call) (const mm-heap-add-area)) + +;; (push (const "== BEGIN HEAP DUMP ==")) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (perform (op call) (const dump-heap)) + +;; (push (const "== END HEAP DUMP ==")) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (assign (temp heap) (op load-array) (const root-heap-pointer) (const 0)) + +;; (push (const 32)) +;; (push (const 32)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-claim-page-range)) + +;; (push (const 32)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-page-empty?)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (const 63)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-page-empty?)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (const 33)) +;; (push (const 4)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-page-range-empty?)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (const 30)) +;; (push (const 2)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-page-range-empty?)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (const 32)) +;; (push (const 1)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-page-range-empty?)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (const 32)) +;; (perform (op call) (const mm-malloc)) +;; (assign (temp mem) (reg accum)) +;; (push (const "malloc pointer: ")) +;; (perform (op call) (const cp-mj-system-out-println)) +;; (push (temp mem)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (temp mem)) +;; (perform (op call) (const mm-free)) + +;; (push (const 32)) +;; (perform (op call) (const mm-malloc)) +;; (assign (temp mem) (reg accum)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (const 6)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-area-malloc)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + + +;; (push (const 64)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-area-malloc)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (push (const 128)) +;; (push (temp heap)) +;; (perform (op call) (const mm-heap-area-malloc)) +;; (push (reg accum)) +;; (perform (op call) (const cp-mj-system-out-println)) + +;; (perform (op pop-frame)) +;; (return (const 0)))) + +(function (name exercise-heap) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (const "asdf")) + (perform (op call) (const cp-mj-system-out-println)) + + (push (const "jkl;")) + (perform (op call) (const cp-mj-system-out-println)) + + (assign (temp leftover) (const 50000)) + + (push (const 56320)) ;; statically configured pointers into machine2 RAM + (push (const 9216)) + (perform (op call) (const mm-heap-add-area)) + + (push (const "exercise heap")) + (perform (op call) (const cp-mj-system-out-println)) + + (assign (temp n-items) (const 32)) + + (push (temp n-items)) + (perform (op call) (const mm-malloc)) + (assign (temp array) (reg accum)) + + (push (temp n-items)) + (perform (op call) (const mm-malloc)) + (assign (temp array-sizes) (reg accum)) + + (assign (temp index) (const 0)) + (label exercise-heap/zero-start) + (branch-zero (label exercise-heap/zero-end) + (result (op less-than) + (temp index) + (temp n-items))) + (perform (op store-array) (temp array) (temp index) (const 0)) + (perform (op store-array) (temp array-sizes) (temp index) (const 0)) + (assign (temp index) (op add) (temp index) (const 1)) + (goto (label exercise-heap/zero-start)) + (label exercise-heap/zero-end) + + (assign (temp index) (const 0)) + (assign (temp iter) (const 0)) + (label exercise-heap/start) + + (push (const "iteration: ")) + (perform (op call) (const cp-mj-system-out-println)) + (push (temp iter)) + (perform (op call) (const cp-mj-system-out-println)) + (push (const "leftover: ")) + (perform (op call) (const cp-mj-system-out-println)) + (push (temp leftover)) + (perform (op call) (const cp-mj-system-out-println)) + + (branch-zero (label exercise-heap/end) + (result (op less-than) (temp iter) (const 1024))) + (assign (temp index) (op bit-and) (temp iter) (const 31)) + + (branch-nonzero (label exercise-heap/free) + (result (op load-array) + (temp array) + (temp index))) + + (assign (temp alloc-amount) (op bit-and) (temp iter) (const 1023)) + (assign (temp leftover) (op sub) (temp leftover) (temp alloc-amount)) + (perform (op store-array) (temp array-sizes) (temp index) (temp alloc-amount)) + (push (temp alloc-amount)) + (perform (op call) (const mm-malloc)) + (perform (op store-array) (temp array) (temp index) (reg accum)) + (branch-nonzero (label exercise-heap/continue) (reg accum)) + (perform (op fail)) + (label exercise-heap/continue) + (assign (temp the-pointer) (reg accum)) + + (push (const "allocating new pointer")) + (perform (op call) (const cp-mj-system-out-println)) + (push (temp index)) + (perform (op call) (const cp-mj-system-out-println)) + (push (temp the-pointer)) + (perform (op call) (const cp-mj-system-out-println)) + + (goto (label exercise-heap/next)) + (label exercise-heap/free) + + (push (const "freeing existing pointer")) + (perform (op call) (const cp-mj-system-out-println)) + (push (temp index)) + (perform (op call) (const cp-mj-system-out-println)) + (push (result (op load-array) (temp array) (temp index))) + (perform (op call) (const cp-mj-system-out-println)) + (push (result (op load-array) (temp array-sizes) (temp index))) + (perform (op call) (const cp-mj-system-out-println)) + + (assign (temp leftover) (op add) (temp leftover) (result (op load-array) (temp array-sizes) (temp index))) + + (push (result (op load-array) (temp array) (temp index))) + (perform (op call) (const mm-free)) + (perform (op store-array) (temp array) (temp index) (const 0)) + + (label exercise-heap/next) + (assign (temp iter) (op add) (temp iter) (const 1)) + (goto (label exercise-heap/start)) + + (label exercise-heap/end) + (perform (op pop-frame)) + (return (const 0)))) diff --git a/src/rtl/heapvar.sasm b/src/rtl/heapvar.sasm new file mode 100644 index 0000000..0558261 --- /dev/null +++ b/src/rtl/heapvar.sasm @@ -0,0 +1,495 @@ +;; rtl/heapvar.sasm +;; Variable-sized allocation heap + +(include "mm-param.sasm") +(include "gc-defines.sasm") + +(export mm-var-heap-add-area) +(export mm-var-heap-area-free) +(export mm-var-heap-area-malloc) +(export mm-var-heap-sweep-area) + +(export mm-var-heap-page-empty?) +(export mm-var-heap-claim-page) +(export mm-var-heap-area-release-page) +(export mm-var-heap-page-range-empty?) +(export mm-var-heap-claim-page-range) + +(define-symconst + (var-heap/words-per-page 32) + (var-heap/shift-words-per-page 5) + (var-heap/mask-words-per-page 31)) + + +(function + (name mm-var-heap-add-area) + (locals 1) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 1)) + + ;; Compute heap parameters: + ;; + ;; bitmap-pages - number of pages described by the heap's allocation bitmap + ;; bitmap-size-words - size of the bitmap in words + ;; pages - number of actual pages left over for use + ;; total-words - total number of words available in the heap + + (assign (temp bitmap-pages:leftover) (op sub) (arg 1) (symconst sizeof:var-heap)) + (assign (temp bitmap-pages:shift) (op bit-rshift) (temp bitmap-pages:leftover) (symconst var-heap/shift-words-per-page)) + (assign (temp bitmap-pages) (op add) (temp bitmap-pages:shift) (const 1)) + + (assign (temp bitmap-size-words) + (op bit-rshift) + (temp bitmap-pages) + (symconst shift-bits-per-word)) + (assign (temp bitmap-size-words) (op add) (temp bitmap-size-words) (const 1)) + + (assign (temp pages:leftover) (op sub) (arg 1) (symconst sizeof:var-heap)) + (assign (temp pages:diff) (op sub) (temp pages:leftover) (temp bitmap-size-words)) + (assign (temp pages) (op bit-rshift) (temp pages:diff) (symconst var-heap/shift-words-per-page)) + + (assign (temp total-words) + (op mul) + (temp pages) + (symconst var-heap/words-per-page)) + (assign (temp bitmap-pointer) + (op add-pointer) + (arg 0) + (symconst sizeof:var-heap)) + + (assign (temp base-pointer:shift) (op bit-lshift) (temp bitmap-size-words) (symconst shift-cells-per-word)) + (assign (temp base-pointer) (op add) (temp bitmap-pointer) (temp base-pointer:shift)) + (assign (temp limit-pointer) (op bit-lshift) (temp total-words) (symconst shift-cells-per-word)) + (assign (temp limit-pointer) (op add) (temp limit-pointer) (temp base-pointer)) + +; (push (temp bitmap-pages:leftover)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp bitmap-pages:shift)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp bitmap-pages)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp bitmap-size-words)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp pages:leftover)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp pages:diff)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp pages)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp total-words)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp bitmap-pointer)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp base-pointer:shift)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp base-pointer)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp limit-pointer)) +; (perform (op call) (const cp-mj-system-out-println)) + + ;; Fill in the heap data structure, link it into the heap + + (perform (op store-array) (arg 0) (symconst heap:base) (temp base-pointer)) + (perform (op store-array) (arg 0) (symconst heap:limit) (temp limit-pointer)) + (perform (op store-array) (arg 0) (symconst heap:object-offset) (const 1)) + (perform (op store-array) (arg 0) (symconst heap:words-per-page) (symconst var-heap/words-per-page)) + (perform (op store-array) (arg 0) (symconst heap:shift-words-per-page) (symconst var-heap/shift-words-per-page)) + (perform (op store-array) (arg 0) (symconst heap:mask-words-per-page) (symconst var-heap/mask-words-per-page)) + (perform (op store-array) (arg 0) (symconst heap:next) (const 0)) + (perform (op store-array) (arg 0) (symconst heap:type) (symconst heap-type:var-alloc)) + (perform (op store-array) (arg 0) (symconst var-heap:hope) (const 0)) + (perform (op store-array) (arg 0) (symconst var-heap:bitmap) (temp bitmap-pointer)) + (perform (op store-array) (arg 0) (symconst var-heap:pages) (temp pages)) + + (assign (temp iter) (temp bitmap-pointer)) + (label mm-var-heap-add-area/begin) + (assign (temp test) (op less-than) (temp iter) (temp base-pointer)) + (branch-zero (label mm-var-heap-add-area/end) (temp test)) + + (perform (op store-array) (temp iter) (const 0) (const 0)) + (assign (temp iter) (op add-pointer) (temp iter) (const 1)) + (goto (label mm-var-heap-add-area/begin)) + + (label mm-var-heap-add-area/end) + +; (perform (op store-array) (const 0) (const 100000000) (const 0)) + (assign (reg accum) (arg 0)) + + (perform (op pop-frame)) + (return (const 2)))) + +;; int mm_var_heap_page_empty_Q( heap *h, int page ) +(function (name mm-var-heap-page-empty?) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp byte-idx) (op bit-rshift) (arg 1) (symconst shift-bits-per-word)) + (assign (temp bit-idx) (op bit-and) (arg 1) (symconst mask-bits-per-word)) + (assign (temp mask) (op bit-lshift) (const 1) (temp bit-idx)) + + (assign (temp bitmap) (op load-array) (arg 0) (symconst var-heap:bitmap)) + (assign (temp word) (op load-array) (temp bitmap) (temp byte-idx)) + (assign (reg accum) (op bit-and) (temp word) (temp mask)) + + (perform (op pop-frame)) + (return (const 2)))) + +;; int mm_var_heap_claim_page( heap *h, int page ) +(function (name mm-var-heap-claim-page) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp byte-idx) (op bit-rshift) (arg 1) (symconst shift-bits-per-word)) + (assign (temp bit-idx) (op bit-and) (arg 1) (symconst mask-bits-per-word)) + (assign (temp mask) (op bit-lshift) (const 1) (temp bit-idx)) + + (assign (temp bitmap) (op load-array) (arg 0) (symconst var-heap:bitmap)) + (assign (temp word) (op load-array) (temp bitmap) (temp byte-idx)) + (assign (reg accum) (op bit-or) (temp word) (temp mask)) + (perform (op store-array) (temp bitmap) (temp byte-idx) (reg accum)) + + (perform (op pop-frame)) + (return (const 2)))) + +(function (name mm-var-heap-area-release-page) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + +; ;; begin DEBUG +; (push (const "heap-release-page")) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (arg 1)) +; (perform (op call) (const cp-mj-system-out-println)) +; ;; end DEBUG + + (assign (temp byte-idx) (op bit-rshift) (arg 1) (symconst shift-bits-per-word)) + (assign (temp bit-idx) (op bit-and) (arg 1) (symconst mask-bits-per-word)) + (assign (temp mask) (op bit-lshift) (const 1) (temp bit-idx)) + + (assign (temp bitmap) (op load-array) (arg 0) (symconst var-heap:bitmap)) + (assign (temp word) (op load-array) (temp bitmap) (temp byte-idx)) + (assign (temp mask) (op bit-not) (temp mask)) + (assign (temp word) (op bit-and) (temp word) (temp mask)) + (perform (op store-array) (temp bitmap) (temp byte-idx) (temp word)) + + (perform (op pop-frame)) + (return (const 2)))) + +;; int mm_var_heap_page_rage_empty_Q( heap *h, int page, int count ) +(function (name mm-var-heap-page-range-empty?) ;; returns int + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp n-pages) (op load-array) (arg 0) (symconst var-heap:pages)) + (assign (temp limit) (op add) (arg 1) (arg 2)) + (assign (temp test) (op less-than-or-equal) (temp limit) (temp n-pages)) + (branch-zero (label mm-var-heap-page-range-empty?/fail) (temp test)) + + (assign (temp idx) (arg 1)) + (label mm-var-heap-page-range-empty?/start) + + (assign (temp test) (op less-than) (temp idx) (temp limit)) + (branch-zero (label mm-var-heap-page-range-empty?/succeed) (temp test)) + + (push (temp idx)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-page-empty?)) + (branch-nonzero (label mm-var-heap-page-range-empty?/fail) (reg accum)) + + (assign (temp idx) (op add) (temp idx) (const 1)) + (goto (label mm-var-heap-page-range-empty?/start)) + + (label mm-var-heap-page-range-empty?/succeed) + (assign (reg accum) (const 1)) + (goto (label mm-var-heap-page-range-empty?/done)) + (label mm-var-heap-page-range-empty?/fail) + (assign (reg accum) (const 0)) + (label mm-var-heap-page-range-empty?/done) + (perform (op pop-frame)) + (return (const 3)))) + +;; int mm_var_heap_claim_page_range( heap *h, int page, int count ) +(function (name mm-var-heap-claim-page-range) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp limit) (op add) (arg 1) (arg 2)) + (assign (temp idx) (arg 1)) + + (label mm-var-heap-claim-page-range/start) + (assign (temp test) (op less-than) (temp idx) (temp limit)) + (branch-zero (label mm-var-heap-claim-page-range/done) (temp test)) + + (push (temp idx)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-claim-page)) + + (assign (temp idx) (op add) (temp idx) (const 1)) + (goto (label mm-var-heap-claim-page-range/start)) + + (label mm-var-heap-claim-page-range/done) + (perform (op pop-frame)) + (return (const 3)))) + +(function (name mm-var-heap-area-free) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp page-pointer) (op sub-pointer) (arg 1) (const 1)) + (assign (temp base) (op load-array) (arg 0) (symconst heap:base)) + (assign (temp cell-offset) (op sub) (temp page-pointer) (temp base)) + (assign (temp word-offset) (op bit-rshift) (temp cell-offset) (symconst shift-cells-per-word)) + (assign (temp page-index) (op bit-rshift) (temp word-offset) (symconst var-heap/shift-words-per-page)) + (assign (temp pages) (op load-array) (temp page-pointer) (const 0)) + (assign (temp page-limit) (op add) (temp page-index) (temp pages)) + +; ;; begin DEBUG +; (push (const "heap-area-free")) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (arg 1)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp page-pointer)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp word-offset)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp page-index)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp pages)) +; (perform (op call) (const cp-mj-system-out-println)) +; (push (temp page-limit)) +; (perform (op call) (const cp-mj-system-out-println)) +; ;; end DEBUG + + (assign (temp idx) (temp page-index)) + (label mm-var-heap-area-free/start) + (assign (temp test) (op less-than) (temp idx) (temp page-limit)) + (branch-zero (label mm-var-heap-area-free/end) (temp test)) + + (push (temp idx)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-area-release-page)) + + (assign (temp idx) (op add) (temp idx) (const 1)) + (goto (label mm-var-heap-area-free/start)) + + (label mm-var-heap-area-free/end) + (perform (op pop-frame)) + (return (const 2)))) + +(function (name mm-var-heap-area-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; final-pointer is where the final result of the malloc + ;; operation is stored + (assign (temp final-pointer) (const 0)) + + ;; initialize some other local variables + ;; + ;; requested - input, # of words requested by user. + ;; Incremented to allow for heap control word. + ;; + ;; pages - # of pages of the heap required to serve the request + ;; + ;; test - temporary used to store the result of bitmask operations + ;; + ;; start - which page to start the search on + ;; + ;; page - current page for this iteration through the search + ;; + ;; n-pages - total # of pages available in the heap + ;; + ;; count - a count of the number of iterations we have completed + ;; in the search + ;; + (assign (temp requested) (op add) (arg 1) (const 1)) + (assign (temp pages) (op bit-rshift) (temp requested) (symconst var-heap/shift-words-per-page)) + (assign (temp test) (op bit-and) (temp requested) (symconst var-heap/mask-words-per-page)) + (branch-zero (label mm-var-heap-area-malloc/nopad) (temp test)) + (assign (temp pages) (op add) (temp pages) (const 1)) + (label mm-var-heap-area-malloc/nopad) + + (assign (temp start) (op load-array) (arg 0) (symconst var-heap:hope)) + (assign (temp page) (temp start)) + (assign (temp n-pages) (op load-array) (arg 0) (symconst var-heap:pages)) + (assign (temp count) (const 0)) + + ;; this is the start of the search loop + (label mm-var-heap-area-malloc/start) + + ;; if we have iterated over the whole heap (n-pages iterations) + ;; then we've run out of possibilites; fail the request + (assign (temp test) (op less-than) (temp count) (temp n-pages)) + (branch-zero (label mm-var-heap-area-malloc/end) (temp test)) + + ;; pages -1 + ;; page -2 + ;; n-pages -3 + ;; count -4 + ;; final-pointer -5 + + ;; check to see if the current page we are looking + ;; at is empty and can hold the requested buffer + (push (temp pages)) ;; -1 + (push (temp page)) ;; -2 + (push (arg 0)) ;; 2 + (perform (op call) (const mm-var-heap-page-range-empty?)) + (branch-zero (label mm-var-heap-area-malloc/try-hope) (reg accum)) + + ;; it can! claim that page range + (push (temp pages)) + (push (temp page)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-claim-page-range)) + + ;; Fill in the size at the head of the allocated buffer. This is + ;; for the use of the heap code. Later when this pointer is free()d + ;; we will need to know the size of the allocation. + (assign (reg accum) (op load-array) (arg 0) (symconst heap:base)) + (assign (temp word-offset) (op bit-lshift) (temp page) (symconst var-heap/shift-words-per-page)) + (perform (op store-array) (reg accum) (temp word-offset) (temp pages)) + + ;; assign final-pointer to the page we just claimed. + ;; final-pointer also needs to be adjusted to not + ;; include the heap control word we added to the alloc + ;; size. + (assign (temp final-pointer:shift) (op bit-lshift) (temp word-offset) (symconst shift-cells-per-word)) + (assign (temp final-pointer) (op add) (reg accum) (temp final-pointer:shift)) + (assign (temp final-pointer) (op add-pointer) (temp final-pointer) (const 1)) +; (assign (temp test-final-pointer) (op less-than) (temp final-pointer) (const 65536)) +; (branch-zero (label mm-var-heap-area-malloc/ptrok) (temp test-final-pointer)) +; (perform (op store-array) (const 0) (const 100000000) (const 0)) +; (label mm-var-heap-area-malloc/ptrok) + + ;; Set up the hope index if possible. If the heap + ;; area adjacent to the one we just claimed is empty, + ;; that is our next hope range. + (assign (temp page) (op add) (temp page) (temp pages)) + + ;; if page + pages > n-pages, wrap around + (assign (temp test) (op less-than) (temp page) (temp n-pages)) + (branch-nonzero (label mm-var-heap-area-malloc/nosubtract) (temp test)) + (assign (temp page) (op sub) (temp page) (temp n-pages)) + (label mm-var-heap-area-malloc/nosubtract) + + ;; If page is empty, then set that as the new hope + ;; index. After that, we're done! Bail out to the + ;; end of the function. + (push (temp page)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-page-empty?)) + (branch-zero (label mm-var-heap-area-malloc/end) (reg accum)) + (perform (op store-array) (arg 0) (symconst var-heap:hope) (temp page)) + (goto (label mm-var-heap-area-malloc/end)) + + (label mm-var-heap-area-malloc/try-hope) + ;; If this page we just tested for a free range + ;; happens to be empty (even though it is not big + ;; enough), set it up as the next hope index. + (push (temp page)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-page-empty?)) + (branch-nonzero (label mm-var-heap-area-malloc/skip) (reg accum)) + + ;; this page is empty, so set it as hope and increment + (perform (op store-array) (arg 0) (symconst var-heap:hope) (temp page)) + + ;; IMPORTANT: this algorithm assumes that it is always + ;; looking at the start of a free or used area. Thus, + ;; we cannot just jump forward by 'pages', because we + ;; might land in the middle of a used region. + (label mm-var-heap-area-malloc/find-start-of-next-used-page) + (assign (temp page) (op add) (temp page) (const 1)) + (assign (temp test) (op less-than) (temp page) (temp n-pages)) + (branch-zero (label mm-var-heap-area-malloc/next) (temp test)) + (push (temp page)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-page-empty?)) + (branch-zero (label mm-var-heap-area-malloc/find-start-of-next-used-page) (reg accum)) + + (label mm-var-heap-area-malloc/skip) + ;; this page is not empty, so skip ahead by the number + ;; of used pages + (assign (reg accum) (op load-array) (arg 0) (symconst heap:base)) + (assign (temp word-offset-2) (op bit-lshift) (temp page) (symconst var-heap/shift-words-per-page)) + (assign (reg accum) (op load-array) (reg accum) (temp word-offset-2)) + (assign (temp page) (op add) (temp page) (reg accum)) + + (label mm-var-heap-area-malloc/next) + ;; each iteration, count=count+1. + (assign (temp count) (op add) (temp count) (const 1)) + ;; test page < n-pages. If not, wrap around + (assign (temp test) (op less-than) (temp page) (temp n-pages)) + (branch-nonzero (label mm-var-heap-area-malloc/start) (temp test)) + (assign (temp page) (const 0)) + (goto (label mm-var-heap-area-malloc/start)) + + (label mm-var-heap-area-malloc/end) + (assign (reg accum) (temp final-pointer)) + (perform (op pop-frame)) + (return (const 2)))) + +(function + (name mm-var-heap-sweep-area) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp base) (op load-array) (arg 0) (symconst heap:base)) + (assign (temp page) (const 0)) + (assign (temp pages) (op load-array) (arg 0) (symconst var-heap:pages)) + (assign (temp cells-per-page) (op bit-lshift) (symconst var-heap/words-per-page) (symconst shift-cells-per-word)) + (assign (temp total-cells) (op mul) (temp pages) (temp cells-per-page)) + (assign (temp limit) (op add) (temp base) (temp total-cells)) + + (label mm-var-heap-sweep-area/begin) + (assign (temp test) (op less-than) (temp page) (temp pages)) + (branch-zero (label mm-var-heap-sweep-area/end) (temp test)) + + (push (temp page)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-page-empty?)) + (branch-zero (label mm-var-heap-sweep-area/empty) (reg accum)) + + (assign (temp pages-to-skip) (op load-array) (temp base) (const 0)) + (assign (temp gcdw) (op load-array) (temp base) (const 2)) + + (assign (temp test) (op bit-and) (temp gcdw) (symconst gcdw:mark-mask)) + (branch-nonzero (label mm-var-heap-sweep-area/inuse) (temp test)) + + ;; the GCDW has the mark bit unset - so we are going to free the pointer + (assign (temp malloc-pointer) (op add-pointer) (temp base) (const 1)) + + (push (temp malloc-pointer)) + (push (arg 0)) + (perform (op call) (const mm-var-heap-area-free)) + (assign (temp gcdw) (const 0)) + + (label mm-var-heap-sweep-area/inuse) + + ;; unmark - make sure the GCDW's mark bit is unset + (assign (temp unmarked-mask) (op bit-not) (symconst gcdw:mark-mask)) + (assign (temp gcdw) (op bit-and) (temp gcdw) (temp unmarked-mask)) + (perform (op store-array) (temp base) (const 2) (temp gcdw)) + + (assign (temp page) (op add) (temp page) (temp pages-to-skip)) + (assign (temp cells-to-skip) (op mul) (temp pages-to-skip) (temp cells-per-page)) + (assign (temp base) (op add) (temp base) (temp cells-to-skip)) + (goto (label mm-var-heap-sweep-area/begin)) + + (label mm-var-heap-sweep-area/empty) + ;; skip ahead to the next page + (assign (temp page) (op add) (temp page) (const 1)) + (assign (temp base) (op add) (temp base) (temp cells-per-page)) + (goto (label mm-var-heap-sweep-area/begin)) + + (label mm-var-heap-sweep-area/end) + (perform (op pop-frame)) + (return (const 1)))) diff --git a/src/rtl/interp-rtlheap.sasm b/src/rtl/interp-rtlheap.sasm new file mode 100644 index 0000000..efe0a55 --- /dev/null +++ b/src/rtl/interp-rtlheap.sasm @@ -0,0 +1,197 @@ +;; interp-rtlheap.sasm +;; +;; Heap stub routines to interface the interpreter to the compiler +;; system + +(export cp-rtl-malloc-failed) +(export rtl-gc-mark-pointer) +(export cp-rtl-malloc) +(export cp-rtl-mark-all-roots) +(export gc-root-stack-limit) + +(extern gc-mark-pointer) +(extern gc-mark-stack-roots) +(extern gc-invoke) +(extern cp-rtl-base-malloc) +(extern mm-heap-add-area) +(extern mm-heap-add-fixed-area) + +;; Normally this global is defined in the C stub. Since there +;; is no such thing for the interpreter, it is defined here. +(global gc-root-stack-limit (const 8192)) + +;; This global tracks whether the interpreter's heap has been +;; initialized yet or not. +(global initialized-heap-already (const 0)) + +(function (name cp-rtl-mark-all-roots) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op call) (label gc-mark-stack-roots)) + + ;; + ;; Mark auxiliary stack pointers. + ;; + + (assign (reg this) (op interp-gc-auxiliary-stack)) + +; ;; begin DEBUG +; (perform (op debug-out) (const "interp-gc-auxiliary-stack=") (reg this)) +; ;; end DEBUG + + (assign (reg operand) (op interp-gc-memory-area-size) (reg this)) + (assign (reg index) (const 0)) + (label mark-auxiliary-stack/begin) + (assign (reg accum) (op less-than) (reg index) (reg operand)) + (branch-zero (label mark-auxiliary-stack/end) (reg accum)) + (assign (reg accum) (op interp-gc-memory-ref) (reg this) (reg index)) + (save (reg this)) + (save (reg operand)) + (save (reg index)) + (push (reg accum)) + (perform (op call) (label rtl-gc-mark-pointer)) + (pop (const 1)) + (restore (reg index)) + (restore (reg operand)) + (restore (reg this)) + + (assign (reg index) (op add) (reg index) (const 1)) + (goto (label mark-auxiliary-stack/begin)) + (label mark-auxiliary-stack/end) + + ;; + ;; Mark global pointers. + ;; + + (assign (reg this) (op interp-gc-global-addrs)) + (assign (reg operand) (op interp-gc-memory-area-size) (reg this)) + (assign (reg index) (const 0)) + (label mark-globals/begin) + (assign (reg accum) (op less-than) (reg index) (reg operand)) + (branch-zero (label mark-globals/end) (reg accum)) + (assign (reg accum) (op interp-gc-memory-ref) (reg this) (reg index)) + (save (reg this)) + (save (reg operand)) + (save (reg index)) + (push (reg accum)) + (perform (op call) (label rtl-gc-mark-pointer)) + (pop (const 1)) + (restore (reg index)) + (restore (reg operand)) + (restore (reg this)) + + (assign (reg index) (op add) (reg index) (const 1)) + (goto (label mark-globals/begin)) + (label mark-globals/end) + + (perform (op pop-frame)) + (return (const 0)))) + +;; This routine wraps gc-mark-pointer. Since this code runs in the +;; interpreter, it checks a memory cell to see if it contains a symbol +;; or other non-numerical value. +(function (name rtl-gc-mark-pointer) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; + ;; This 'not-an-number' operation is only supported by + ;; the interpreter. + ;; + + (test (op interp-gc-not-a-number) (arg 0)) + (branch-false (label rtl-gc-mark-pointer/address)) + + ;; + ;; The address is not a number. It could be a + ;; symbolic interpreter address, however it might be + ;; something else such as a return address. Rule such + ;; objects out first. + ;; + + (test (op interp-gc-test-symbolic-pointer) (arg 0)) + (branch-false (label rtl-gc-mark-pointer/end)) + + ;; + ;; The address is a symbolic interpreter address that + ;; references a memory area. We can use a couple of + ;; specialized interpreter operations to walk that + ;; memory area and mark any pointers. + ;; + + (assign (reg operand) (op interp-gc-memory-area-size) (arg 0)) + (assign (reg index) (const 0)) + + (label walk-symbolic-memory-area/begin) + (assign (reg accum) (op less-than) (reg index) (reg operand)) + (branch-zero (label rtl-gc-mark-pointer/end) (reg accum)) + (assign (reg accum) (op interp-gc-memory-ref) (arg 0) (reg index)) + (save (reg index)) + (save (reg operand)) + (push (reg accum)) + (perform (op call) (label rtl-gc-mark-pointer)) + (pop (const 1)) + (restore (reg operand)) + (restore (reg index)) + (assign (reg index) (op add) (reg index) (const 1)) + (goto (label walk-symbolic-memory-area/begin)) + + (label rtl-gc-mark-pointer/address) + (push (arg 0)) + (perform (op call) (const gc-mark-pointer)) + + (label rtl-gc-mark-pointer/end) + (perform (op pop-frame)) + (return (const 0)))) + +(function (name cp-rtl-malloc-failed) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; This operation isn't actually supported by the + ;; interpreter, but it will cause the interpreter to + ;; stop. + (perform (op debug-break)) + (assign (reg accum) (const 0)) + + (perform (op pop-frame)) + (return (const 1)))) + +(function (name cp-rtl-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; Check to see if we've already initialized the heap. + (assign (temp test) (op load-array) (const initialized-heap-already) (const 0)) + (test (op nonzero) (temp test)) + (branch-true (label cp-rtl-malloc/initialized)) + + ;; Add a variable-sized allocation heap area. + (push (const 40320)) + (push (const 9216)) + (perform (op call) (const mm-heap-add-area)) + + ;; Add a fixed-size allocation heap area. + (push (const 16000)) + (push (const 16)) + (push (const 49536)) + (perform (op call) (const mm-heap-add-fixed-area)) + + ;; Remember that we initialized the heap. + (perform (op store-array) (const initialized-heap-already) (const 0) (const 1)) + + (label cp-rtl-malloc/initialized) + + ;; Call the underlying malloc function, result in accum. + (push (arg 0)) + (perform (op call) (const cp-rtl-base-malloc)) + + ;; Done. + (perform (op pop-frame)) + (return (const 1)))) + diff --git a/src/rtl/makefile b/src/rtl/makefile new file mode 100644 index 0000000..bfa20ef --- /dev/null +++ b/src/rtl/makefile @@ -0,0 +1,14 @@ +CPP = cpp +CPP_ARGS = -C -P + +scheme.java : scheme.javap + $(CPP) $(CPP_ARGS) -DTESTING=0 -o scheme.java scheme.javap + +scheme_test.java : scheme.javap + $(CPP) $(CPP_ARGS) -DTESTING=1 -o scheme_test.java scheme.javap + +scheme_test.exe : scheme_test.java + gcj --main=scheme_test scheme_test.java -o scheme_test.exe + +clean: + rm -f scheme_test.java scheme_test.exe *~ diff --git a/src/rtl/mjrtl-spim.sasm b/src/rtl/mjrtl-spim.sasm new file mode 100644 index 0000000..88eb022 --- /dev/null +++ b/src/rtl/mjrtl-spim.sasm @@ -0,0 +1,39 @@ +;; mjrtl-mips.sasm +;; MIPS runtime library for use in SPIM, implemented in MIPS-specific SASM + +(export cp-mj-system-out-println) +(export c-fail-malloc) + +(global mjrtl-string-prefix + (const :asciiz "@SYSTEM-OUT-PRINTLN ")) +(global mjrtl-string-newline + (const :asciiz "\n")) +(global mjrtl-string-fail + (const :asciiz "failed malloc ")) + +(function (name cp-mj-system-out-println) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op mips-system-call) (const 4) (label mjrtl-string-prefix)) + (perform (op mips-system-call) (const 1) (arg 0)) + (perform (op mips-system-call) (const 4) (label mjrtl-string-newline)) + (assign (reg accum) (arg 0)) + + (perform (op pop-frame)) + (return (const 1)))) + +(function (name c-fail-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op mips-system-call) (const 4) (label mjrtl-string-fail)) + (perform (op mips-system-call) (const 1) (arg 0)) + (perform (op mips-system-call) (const 4) (label mjrtl-string-newline)) + + (perform (op mips-system-call) (const 10) (const 0)) + + (perform (op pop-frame)) + (return))) diff --git a/src/rtl/mjrtl.c b/src/rtl/mjrtl.c new file mode 100644 index 0000000..330665b --- /dev/null +++ b/src/rtl/mjrtl.c @@ -0,0 +1,103 @@ +// mjrtl.c +// Very tiny runtime library for MiniJava programs +#include +#include +#include + +extern void SYM(sasm_entry)(void); +extern void SYM(c_mm_heap_add_area)( void *base, int words ); +extern void SYM(c_mm_heap_add_fixed_area)( void *base, int chunk, int words ); +void *SYM(gc_root_stack_limit); + +#define VARIABLE_HEAP_SIZE ( 128 * 1024 * 1024 * sizeof(int) ) +#define FIXED_HEAP_SIZE ( 128 * 1024 * 1024 * sizeof(int) ) +#define FIXED_HEAP_CHUNK 16 +#define RTL_VARIABLE_HEAP 1 +#define RTL_FIXED_HEAP 1 +#define RTL_2ND_FIXED_HEAP 0 + +#if SCHEME_RTL +extern void rtlscheme_init_argv(int argc, char **argv); +#endif + +int _tmain( int argc, TCHAR *argv[] ) +{ + void *pHeap; + void *pHeapFixed; + void *pHeapFixed2; + + SYM(gc_root_stack_limit) = &pHeap; + +#if RTL_VARIABLE_HEAP + pHeap = malloc( VARIABLE_HEAP_SIZE ); + if( NULL == pHeap ) + { + _tprintf( TEXT("error allocating heap\n") ); + ExitProcess( 1 ); + } + + memset( pHeap, 0, VARIABLE_HEAP_SIZE ); + + SYM(c_mm_heap_add_area)( pHeap, + VARIABLE_HEAP_SIZE / sizeof(int) ); +#endif /* RTL_VARIABLE_HEAP */ + +#if RTL_FIXED_HEAP + pHeapFixed = malloc( FIXED_HEAP_SIZE ); + if( NULL == pHeapFixed ) + { + _tprintf( TEXT("error allocating fixed heap\n") ); + ExitProcess( 1 ); + } + memset( pHeapFixed, 0, FIXED_HEAP_SIZE ); + SYM(c_mm_heap_add_fixed_area)( pHeapFixed, + FIXED_HEAP_CHUNK, + FIXED_HEAP_SIZE / sizeof(int) ); +#endif /* RTL_FIXED_HEAP */ + +#if RTL_2ND_FIXED_HEAP + pHeapFixed2 = malloc( FIXED_HEAP_SIZE ); + if( NULL == pHeapFixed2 ) + { + _tprintf( TEXT("error allocating second fixed heap\n") ); + ExitProcess( 1 ); + } + memset( pHeapFixed2, 0, FIXED_HEAP_SIZE ); + SYM(c_mm_heap_add_fixed_area)( pHeapFixed2, + FIXED_HEAP_CHUNK, + FIXED_HEAP_SIZE / sizeof(int) ); +#endif /* RTL_2ND_FIXED_HEAP */ + +#if SCHEME_RTL + rtlscheme_init_argv(argc, argv); +#endif /* SCHEME_RTL */ + + SYM(sasm_entry)(); + return 0; +} + +int SYM(mj_system_out_println)( int arg ) +{ + _tprintf( TEXT("%d\n"), arg ); + fflush( stdout ); + return arg; +} + +int SYM(mj_system_out_println_string)( TCHAR *s ) +{ + _tprintf( TEXT("MESSAGE [%s]\n"), s ); + fflush( stdout ); + return 0; +} + +int SYM(c_fail_malloc)( int words ) +{ + _tprintf( TEXT("failed to allocate %u words of memory!\n"), words ); + ExitProcess( 1 ); +} + +int SYM(c_fail_bad_heap_check)(void) +{ + _tprintf(TEXT("heap consistency check failed")); + ExitProcess(1); +} diff --git a/src/rtl/mjrtl.sasm b/src/rtl/mjrtl.sasm new file mode 100644 index 0000000..0162c5d --- /dev/null +++ b/src/rtl/mjrtl.sasm @@ -0,0 +1,15 @@ +;; mjrtl.sasm +;; callee-pop versions of mjrtl functions + +(extern mj-system-out-println) +(export cp-mj-system-out-println) + +(function (name cp-mj-system-out-println) + (locals 0) + (body (perform (op push-frame)) + (push (arg 0)) + (perform (op call) (const mj-system-out-println)) +; (pop (const 1)) + (perform (op pop-frame)) + (return (const 1)))) + diff --git a/src/rtl/mm-param.sasm b/src/rtl/mm-param.sasm new file mode 100644 index 0000000..743134c --- /dev/null +++ b/src/rtl/mm-param.sasm @@ -0,0 +1,54 @@ +;; mm-param.sasm +;; Definitions for shared parameters of heap management and garbage collection + +(define-symconst + + ;; == general heap data structure == + ;; all heap subclasses must at a minimum + ;; provide this object layout. + ;; + ;; operations on heaps: + ;; + ;; - get the base and limit of a heap, to determine if a pointer + ;; falls within that heap + ;; + ;; - get the offset of an aliased pointer within a heap page (need + ;; base, shift-words-per-page, mask-words-per-page) + ;; + ;; + (sizeof:heap 8) + (heap:base 0) + (heap:limit 1) + (heap:object-offset 2) + (heap:words-per-page 3) + (heap:shift-words-per-page 4) + (heap:mask-words-per-page 5) + (heap:next 6) + (heap:type 7) + + (heap-type:fixed-alloc #xdeadface) + (heap-type:var-alloc #xbaadf00d) + + ;; variable-sized heap data structure + (sizeof:var-heap 12) + (var-heap:hope 9) + (var-heap:bitmap 10) + (var-heap:pages 11) + + ;; fixed-allocation heap data structure + (sizeof:fixed-heap 10) + (fixed-heap:free-list 8) + (fixed-heap:next-fixed-heap 9) + + ) + + +;; (assign (temp pages) (op load-array) (temp heap) (symconst heap:pages)) +;; (assign (temp words) (op mul) (temp pages) (symconst-bad words-per-page)) +;; (assign (temp cells) (op bit-lshift) (temp words) (symconst-bad shift-cells-per-word)) + + +;; - (words-per-page 32) +;; - (shift-words-per-page 5) +;; - (mask-words-per-page 31) +;; - (words-per-heap-header 8) diff --git a/src/rtl/nonexports.scm b/src/rtl/nonexports.scm new file mode 100644 index 0000000..390cae8 --- /dev/null +++ b/src/rtl/nonexports.scm @@ -0,0 +1,22 @@ +;; nonexports.scm +;; +;; A quick and dirty program to print out the non-exported functions +;; in a SASM file. It prints these out in (export) statements so that +;; they can be easily cut-and-pasted pasted into another sasm file. +;; +;; Run like so: mzscheme --script nonexports.scm = i (vector-length a)) + #t + (and (equal? (vector-ref a i) (vector-ref b i)) (iter (+ i 1))))) + (and (= (vector-length a) (vector-length b)) + (iter 0))) + (define (pair-equal? a b) + (if (or (not (pair? a)) (not (pair? b))) + (equal? a b) + (and (equal? (car a) (car b)) (equal? (cdr a) (cdr b))))) + (define (string-equal? a b) + (define (iter i) + (if (>= i (string-length a)) + #t + (and (char=? (string-ref a i) (string-ref b i)) + (iter (+ i 1))))) + (and (= (string-length a) (string-length b)) + (iter 0))) + (cond ((and (vector? a) (vector? b)) (vector-equal? a b)) + ((and (pair? a) (pair? b)) (pair-equal? a b)) + ((and (string? a) (string? b)) (string-equal? a b)) + (else (eqv? a b)))) + +(define (zero? z) (= z 0)) +(define (positive? x) (> x 0)) +(define (negative? x) (< x 0)) +; TODO: revive +;(define (odd? n) (not (even? n))) +;(define (even? n) (zero? (remainder n 2))) + +; r5rs specifies max requires at least 2 arguments but as an extension many +; scheme implementations tolerate calling it with a single argument, which +; results in code that depends on that behavior. For compatibility, it is also +; supported by this implementation. +(define (max num1 . numbers) + (define (max2 a b) (if (> a b) a b)) + (define (iter r l) + (if (null? l) r (iter (max2 r (car l)) (cdr l)))) + (if (null? numbers) + num1 + (iter (max2 num1 (car numbers)) (cdr numbers)))) + +(define (min num1 . numbers) + (define (min2 a b) (if (< a b) a b)) + (define (iter r l) + (if (null? l) r (iter (min2 r (car l)) (cdr l)))) + (if (null? numbers) + num1 + (iter (min2 num1 (car numbers)) (cdr numbers)))) + +(define (abs x) + (if (negative? x) (- x) x)) + +; TODO: revive +;(define (gcd a b) +; (if (zero? b) +; a +; (gcd b (remainder a b)))) + +; TODO: revive +;(define (lcm a b) +; (/ (* a b) (gcd a b))) + +;; TODO: fix this, revive +;(define (rationalize x y) +; (/ (inexact->exact (numerator x)) +; (inexact->exact (denominator y)))) + +;(define (my-string->number s . def-radix-list) +; (define def-radix (if (null? def-radixlist) 10 (car def-radix-list))) +; (define valid-radices (list 2 8 10 16)) +; (define hex-digits '((#\0 . 0) (#\1 . 1) (#\2 . 2) (#\3 . 3) +; (#\4 . 4) (#\5 . 5) (#\6 . 6) (#\7 . 7) +; (#\8 . 8) (#\9 . 9) (#\a . 10) (#\A . 10) +; (#\b . 11) (#\B . 11) (#\c . 12) (#\C . 12) +; (#\d . 13) (#\D . 13) (#\e . 14) (#\E . 14) +; (#\f . 15) (#\F . 15))) +; (define decimal-digits '((#\0 . 0) (#\1 . 1) (#\2 . 2) (#\3 . 3) (#\4 . 4) +; (#\5 . 5) (#\6 . 6) (#\7 . 7) (#\8 . 8) (#\9 . 9))) +; (define binary-digits '((#\0 . 0) (#\1 . 1))) +; (define octal-digits '((#\0 . 0) (#\1 . 1) (#\2 . 2) (#\3 . 3) (#\4 . 4) +; (#\5 . 5) (#\6 . 6) (#\7 . 7))) +; (define (parse-number digits base charmap) +; (define (iter res digits) +; (if (null? digits) +; res +; (iter (+ (* res base) (cdr (assoc (car digits) charmap))) +; (cdr digits)))) +; (iter 0 digits)) +; (parse-number (string->list s) 16 hex-digits)) + +(define (not obj) + (eq? #f obj)) + +(define (boolean? obj) + (or (eq? #f obj) + (eq? #t obj))) + +(define (caar pair) (car (car pair))) +(define (cadr pair) (car (cdr pair))) +(define (cdar pair) (cdr (car pair))) +(define (cddr pair) (cdr (cdr pair))) +(define (caaar pair) (car (car (car pair)))) +(define (caadr pair) (car (car (cdr pair)))) +(define (cadar pair) (car (cdr (car pair)))) +(define (caddr pair) (car (cdr (cdr pair)))) +(define (cdaar pair) (cdr (car (car pair)))) +(define (cdadr pair) (cdr (car (cdr pair)))) +(define (cddar pair) (cdr (cdr (car pair)))) +(define (cdddr pair) (cdr (cdr (cdr pair)))) +(define (caaaar pair) (car (car (car (car pair))))) +(define (caaadr pair) (car (car (car (cdr pair))))) +(define (caadar pair) (car (car (cdr (car pair))))) +(define (caaddr pair) (car (car (cdr (cdr pair))))) +(define (cadaar pair) (car (cdr (car (car pair))))) +(define (cadadr pair) (car (cdr (car (cdr pair))))) +(define (caddar pair) (car (cdr (cdr (car pair))))) +(define (cadddr pair) (car (cdr (cdr (cdr pair))))) +(define (cdaaar pair) (cdr (car (car (car pair))))) +(define (cdaadr pair) (cdr (car (car (cdr pair))))) +(define (cdadar pair) (cdr (car (cdr (car pair))))) +(define (cdaddr pair) (cdr (car (cdr (cdr pair))))) +(define (cddaar pair) (cdr (cdr (car (car pair))))) +(define (cddadr pair) (cdr (cdr (car (cdr pair))))) +(define (cdddar pair) (cdr (cdr (cdr (car pair))))) +(define (cddddr pair) (cdr (cdr (cdr (cdr pair))))) + +(define (null? obj) + (eq? '() obj)) + +(define (list? pair) + (define (iter slow fast) + (cond ((or (null? slow) (null? fast)) #t) + ((or (not (pair? slow)) (not (pair? fast))) #f) + ((eq? slow fast) #f) + ((null? (cdr fast)) #t) + ((not (pair? (cdr fast))) #f) + (else (iter (cdr slow) (cddr fast))))) + (or (null? pair) + (and (pair? pair) + (iter pair (cdr pair))))) + +(define (list . args) args) + +(define (length list) + (define (iter i l) + (if (null? l) i (iter (+ i 1) (cdr l)))) + (iter 0 list)) + +(define (append list . lists) + (define (append2 a b) + (if (null? a) + b + (cons (car a) (append2 (cdr a) b)))) + (define (iter r l) + (if (null? l) + r + (iter (append2 r (car l)) (cdr l)))) + (iter list lists)) + +(define (reverse list) + (define (iter r l) + (if (null? l) + r + (iter (cons (car l) r) + (cdr l)))) + (iter '() list)) + +(define (list-tail list k) + (if (zero? k) + list + (list-tail (cdr list) (- k 1)))) + +(define (list-ref list k) + (if (zero? k) + (car list) + (list-ref (cdr list) (- k 1)))) + +(define (memq obj list) + (cond ((null? list) #f) + ((eq? obj (car list)) list) + (else (memq obj (cdr list))))) + +(define (memv obj list) + (cond ((null? list) #f) + ((eqv? obj (car list)) list) + (else (memv obj (cdr list))))) + +(define (member obj list) + (cond ((null? list) #f) + ((equal? obj (car list)) list) + (else (member obj (cdr list))))) + +(define (assq obj alist) + (cond ((null? alist) #f) + ((eq? obj (caar alist)) (car alist)) + (else (assq obj (cdr alist))))) + +(define (assv obj alist) + (cond ((null? alist) #f) + ((eqv? obj (caar alist)) (car alist)) + (else (assv obj (cdr alist))))) + +(define (assoc obj alist) + (cond ((null? alist) #f) + ((equal? obj (caar alist)) (car alist)) + (else (assoc obj (cdr alist))))) + +(define (char-ci=? char1 char2) + (char=? (char-downcase char1) (char-downcase char2))) + +(define (char-ci? char1 char2) + (char>? (char-downcase char1) (char-downcase char2))) + +(define (char-ci<=? char1 char2) + (char<=? (char-downcase char1) (char-downcase char2))) + +(define (char-ci>=? char1 char2) + (char>=? (char-downcase char1) (char-downcase char2))) + +(define (char-alphabetic? char) + (or (char-upper-case? char) (char-lower-case? char))) + +(define (char-numeric? char) + (if (member char + (list #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)) + #t + #f)) + +(define (char-whitespace? char) + (if (member char + (list #\space #\newline (integer->char 13) (integer->char 9))) + #t + #f)) + +(define (char-lower-case? char) + (if (member char + (list #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m + #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z)) + #t + #f)) + +(define (char-upper-case? char) + (if (member char + (list #\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\K #\L #\M + #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z)) + #t + #f)) + +(define (char-upcase char) + (let ((a (assoc char '((#\a . #\A) (#\b . #\B) (#\c . #\C) (#\d . #\D) + (#\e . #\E) (#\f . #\F) (#\g . #\G) (#\h . #\H) + (#\i . #\I) (#\j . #\J) (#\k . #\K) (#\l . #\L) + (#\m . #\M) (#\n . #\N) (#\o . #\O) (#\p . #\P) + (#\q . #\Q) (#\r . #\R) (#\s . #\S) (#\t . #\T) + (#\u . #\U) (#\v . #\V) (#\w . #\W) (#\x . #\X) + (#\y . #\y) (#\z . #\Z))))) + (if a (cdr a) char))) + +(define (char-downcase char) + (let ((a (assoc char '((#\A . #\a) (#\B . #\b) (#\C . #\c) (#\D . #\d) + (#\E . #\e) (#\F . #\f) (#\G . #\g) (#\H . #\h) + (#\I . #\i) (#\J . #\j) (#\K . #\k) (#\L . #\l) + (#\M . #\m) (#\N . #\n) (#\O . #\o) (#\P . #\p) + (#\Q . #\q) (#\R . #\r) (#\S . #\s) (#\T . #\t) + (#\U . #\u) (#\V . #\v) (#\W . #\w) (#\X . #\x) + (#\Y . #\y) (#\Z . #\z))))) + (if a (cdr a) char))) + +(define (string . chars) + (list->string chars)) + +(define (string=? s1 s2) + (define (iter i) + (cond ((>= i (string-length s1)) #t) + ((char=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else #f))) + (and (= (string-length s1) (string-length s2)) + (iter 0))) + +(define (string-ci=? s1 s2) + (define (iter i) + (cond ((>= i (string-length s1)) #t) + ((char-ci=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else #f))) + (if (= (string-length s1) (string-length s2)) + (iter 0) + #f)) + +(define (string= i (string-length s1)) + (>= i (string-length s2))) + (< (string-length s1) (string-length s2))) + ((char=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char? s1 s2) + (define (iter i) + (cond ((or (>= i (string-length s1)) + (>= i (string-length s2))) + (> (string-length s1) (string-length s2))) + ((char=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char>? (string-ref s1 i) (string-ref s2 i))))) + (iter 0)) + +(define (string<=? s1 s2) + (define (iter i) + (cond ((or (>= i (string-length s1)) + (>= i (string-length s2))) + (<= (string-length s1) (string-length s2))) + ((char=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char<=? (string-ref s1 i) (string-ref s2 i))))) + (iter 0)) + +(define (string>=? s1 s2) + (define (iter i) + (cond ((or (>= i (string-length s1)) + (>= i (string-length s2))) + (>= (string-length s1) (string-length s2))) + ((char=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char>=? (string-ref s1 i) (string-ref s2 i))))) + (iter 0)) + +(define (string-ci= i (string-length s1)) + (>= i (string-length s2))) + (< (string-length s1) (string-length s2))) + ((char-ci=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char-ci? s1 s2) + (define (iter i) + (cond ((or (>= i (string-length s1)) + (>= i (string-length s2))) + (> (string-length s1) (string-length s2))) + ((char-ci=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char-ci>? (string-ref s1 i) (string-ref s2 i))))) + (iter 0)) + +(define (string-ci<=? s1 s2) + (define (iter i) + (cond ((or (>= i (string-length s1)) + (>= i (string-length s2))) + (<= (string-length s1) (string-length s2))) + ((char-ci=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char-ci<=? (string-ref s1 i) (string-ref s2 i))))) + (iter 0)) + +(define (string-ci>=? s1 s2) + (define (iter i) + (cond ((or (>= i (string-length s1)) + (>= i (string-length s2))) + (>= (string-length s1) (string-length s2))) + ((char-ci=? (string-ref s1 i) (string-ref s2 i)) (iter (+ i 1))) + (else (char-ci>=? (string-ref s1 i) (string-ref s2 i))))) + (iter 0)) + +(define (substring string start end) + (define (iter r i) + (if (< i end) + (iter (cons (string-ref string i) r) (+ i 1)) + (list->string (reverse r)))) + (iter '() start)) + +(define (string-append s1 . s2) + (define (append2 s1 s2) + (list->string (append (string->list s1) (string->list s2)))) + (define (iter res args) + (if (null? args) + res + (iter (append2 res (car args)) (cdr args)))) + (iter s1 s2)) + +(define (string->list string) + (define (iter r i) + (if (>= i 0) + (iter (cons (string-ref string i) r) (- i 1)) + r)) + (iter '() (- (string-length string) 1))) + +(define (list->string list) + (let ((s (make-string (length list)))) + (define (iter i l) + (if (null? l) + s + (begin (string-set! s i (car l)) (iter (+ i 1) (cdr l))))) + (iter 0 list))) + +(define (string-copy string) + (list->string (string->list string))) + +(define (string-fill! string char) + (let ((len (string-length string))) + (define (iter i) + (if (< i len) + (begin (string-set! string i char) + (iter (+ i 1))))) + (iter 0))) + +(define (vector . args) + (list->vector args)) + +(define (vector->list vec) + (define (iter r i) + (if (>= i 0) + (iter (cons (vector-ref vec i) r) (- i 1)) + r)) + (iter '() (- (vector-length vec) 1))) + +(define (list->vector list) + (let ((vec (make-vector (length list)))) + (define (iter i l) + (if (not (null? l)) + (begin (vector-set! vec i (car l)) (iter (+ i 1) (cdr l))) + vec)) + (iter 0 list))) + +(define (vector-fill! vec obj) + (define (iter i) + (if (< i (vector-length vec)) + (begin (vector-set! vec i obj) (iter (+ i 1))))) + (iter 0)) + +(define (map proc list . lists) + (define (any-null? list) + (cond ((null? list) #f) + ((null? (car list)) #t) + (else (any-null? (cdr list))))) + (define (cars list) + (define (iter r list) + (if (null? list) + (reverse r) + (iter (cons (caar list) r) (cdr list)))) + (iter '() list)) + (define (cdrs list) + (define (iter r list) + (if (null? list) + (reverse r) + (iter (cons (cdar list) r) (cdr list)))) + (iter '() list)) + (define (iter res lists) + (if (any-null? lists) + (reverse res) + (iter (cons (apply proc (cars lists)) res) + (cdrs lists)))) + (if (null? lists) + (let loop ((r '()) (l list)) + (if (null? l) + (reverse r) + (loop (cons (proc (car l)) r) + (cdr l)))) + (iter '() (cons list lists)))) + +(define (for-each proc list . lists) + (define (any-null? list) + (cond ((null? list) #f) + ((null? (car list)) #t) + (else (any-null? (cdr list))))) + (define (iter lists) + (if (and (not (null? lists)) (not (any-null? lists))) + (begin (apply proc (map car lists)) + (iter (map cdr lists))))) + (if (null? lists) + (let loop ((l list)) + (if (not (null? l)) + (begin (proc (car l)) + (loop (cdr l))))) + (iter (cons list lists)))) + +(define (force promise) + (promise)) + +(define (call-with-input-file string proc) + (let ((file (open-input-file string))) + (let ((val (proc file))) + (close-input-port file) + val))) + +(define (call-with-output-file string proc) + (let ((file (open-output-file string))) + (let ((val (proc file))) + (close-output-port file) + val))) + +;#DEFINE READER_EXTENSIONS +;#IFDEF READER_EXTENSIONS +(define *reader-extensions* '()) + +(define (install-reader-extension start reader) + (set! *reader-extensions* (cons (cons start reader) + *reader-extensions*))) +;#ENDIF READER_EXTENSIONS + +(define (read . port) + (define (read port) + (define standard-delimiters + (list->string (list #\space #\( #\) #\newline #\" #\; #\" + (integer->char 13) (integer->char 9)))) + (define (eat char) + (if (or (and (char? char) (char=? char (read-char port))) + (member (read-char port) char)) + #t + (error "Expecting other character -- READ" port char))) + (define (read-until char) + (define (iter res) + (if (or (eof-object? (peek-char port)) + (and (char? char) (char=? (peek-char port) char)) + (and (string? char) (member (peek-char port) + (string->list char))) + (and (list? char) (member (peek-char port) char))) + (list->string (reverse res)) + (iter (cons (read-char port) res)))) + (iter '())) + (define (eat-comment) + (read-until #\newline)) + (define (eat-whitespace) + (if (char-whitespace? (peek-char port)) + (begin (read-char port) (eat-whitespace)) + (if (char=? #\; (peek-char port)) + (begin (eat-comment) + (eat-whitespace) + )))) + (define (fix-improper head tail) + (if (null? head) + tail + (fix-improper (cdr head) (cons (car head) tail)))) + (define (read-list l) + (eat-whitespace) + (cond ((eof-object? (peek-char port)) + (error + "Input was terminated while looking for a closing parens.")) + ((char=? (peek-char port) #\)) (read-char port) (reverse l)) + (else + (let ((elem (read port))) + (if (and (symbol? elem) (string=? "." (symbol->string elem))) + (let ((ans (fix-improper l (read port)))) + (eat-whitespace) + (eat #\)) + ans) + (read-list (cons elem l))))))) + (define (read-string res) + (let ((char (read-char port))) + (cond ((eof-object? char) (list->string (reverse res))) + ((char=? #\\ char) + (let* ((next-char (read-char port)) + (entry (cond ((char=? next-char #\t) (integer->char #x09)) + ((char=? next-char #\r) (integer->char #x0d)) + ((char=? next-char #\n) #\newline) + ((char=? next-char #\\) #\\) + ((char=? next-char #\") #\") + (else #f)))) + (if entry + (read-string (cons entry res)) + (error "Invalid character escape - " next-char)))) + ((char=? #\" char) (list->string (reverse res))) + (else (read-string (cons char res)))))) + (define (read-char-lit) + (eat #\\) + (case (peek-char port) + ((#\; #\( #\) #\" #\;) (read-char port)) + ((#\space #\newline (integer->char 13)) + (error "Invalid character constant." (peek-char port))) + (else + (if (eof-object? (peek-char port)) + (error "Reached end-of-file in character constant.") + (let ((name (read-until standard-delimiters))) + (if (= (string-length name) 1) + (string-ref name 0) + (let ((char (cond ((string=? name "newline") #\newline) + ((string=? name "carriage-return") (integer->char #x0d)) + ((string=? name "space") #\space) + ((string=? name "tab") (integer->char #x09)) + (else #f)) + )) + (if char + char + (error "An invalid character name was specified." + name))))))))) + (define (parse-id-or-num string) + (define n (string-length string)) + (define special-initial '(#\! #\$ #\% #\& #\* #\/ #\: #\< #\= #\> #\? #\^ #\_ #\~ #\@)) + (define special-subsequent '(#\+ #\- #\. #\@)) + (define peculiar-identifier '("+" "-" "." "...")) + (define (ident-initial? c) + (or (char-alphabetic? c) + (memv c special-initial))) + (define (ident-subsequent? c) + (or (ident-initial? c) + (char-numeric? c) + (member c special-subsequent))) + (define (valid-id? i) + (if (>= i n) + #t + (and (ident-subsequent? (string-ref string i)) + (valid-id? (+ i 1))))) + (if (zero? n) + (error "Read - unable to parse the empty string") + (let ((first (string-ref string 0))) + (cond ((member string peculiar-identifier) + (string->symbol string)) + ((or (char-numeric? first) + (char=? first #\-)) + (let ((result (string->number string))) + (if (not result) + (error "Unable to parse string as number" string) + result))) + ((ident-initial? first) + (if (valid-id? 1) + (string->symbol string) + (error "Unable to parse string as symbol" string))) + ((and (char=? #\# first) + (> n 1) + (char=? #\x (string-ref string 1))) + (let ((result (string->number (substring string 2 n) 16))) + (if result + result + (error "Unable to parse hex string as number" string)))) + (else + (error "Unrecognized token" string)))))) + (let* ((char (read-char port)) + (next (if (eof-object? char) char (peek-char port)))) + (cond ((eof-object? char) char) + ((char=? #\; char) (begin (eat-comment) + (read port))) + ((char-whitespace? char) (read port)) + ((and (char=? #\# char) (char=? #\\ next)) + (read-char-lit)) + ((and (char=? #\# char) (char=? #\t (char-downcase next))) + (begin (read-char port) + #t)) + ((and (char=? #\# char) (char=? #\f (char-downcase next))) + (begin (read-char port) + #f)) + ((and (char=? #\# char) (char=? #\( next)) + (read-char port) (list->vector (read-list '()))) +;#IFDEF READER_EXTENSIONS + ((and (char=? #\# char) (assoc next *reader-extensions*)) + (let ((reader (cdr (assoc next *reader-extensions*)))) + (reader port))) +;#ENDIF READER_EXTENSIONS + ((char=? #\' char) (list 'quote (read port))) + ((char=? #\` char) (list 'quasiquote (read port))) + ((char=? #\, char) (if (char=? next #\@) + (begin (read-char port) + (list 'unquote-splicing + (read port))) + (list 'unquote (read port)))) + ((char=? #\" char) (read-string '())) + ((char=? #\( char) + + (read-list '())) + (else + (let ((the-string (string-append + (string char) + (read-until standard-delimiters)))) + (parse-id-or-num the-string)))))) + (read (if (null? port) + (current-input-port) + (car port)))) + +(define (write obj . port-list) + (if (null? port-list) + (write obj (current-output-port)) + (let ((port (car port-list)) + (wri (lambda objs (for-each (lambda (obj) + (write obj (car port-list))) + objs))) + (disp (lambda objs (for-each (lambda (obj) + (display obj (car port-list))) + objs)))) + (define (char-name char) + (case char + ((#\newline) "newline") + ((#\space) "space") + (else (cond ((char=? char (integer->char #x09)) "tab") + ((char=? char (integer->char #x0d)) "carriage-return") + (else (string char)))))) + (define (wri-char char) + (cond ((char=? char (integer->char #x09)) + (disp #\\) (disp #\t)) + ((char=? char (integer->char #x0d)) + (disp #\\) (disp #\r)) + ((char=? char #\newline) + (disp #\\) (disp #\n)) + (else + (case char + ((#\") (disp #\\) (disp #\")) + ((#\\) (disp #\\) (disp #\\)) + (else (disp char)))))) + (define (wri-pair prefix obj) + (cond ((null? obj) (disp ")")) + ((pair? obj) + (disp prefix) (wri (car obj)) (wri-pair " " (cdr obj))) + (else (disp prefix "." prefix) (wri obj) (disp ")")))) + (cond ((char? obj) (disp "#\\") (disp (char-name obj))) + ((string? obj) + (disp #\") + (for-each wri-char (string->list obj)) + (disp #\")) + ((pair? obj) (wri-pair "(" obj)) + ((vector? obj) (disp "#") (write (vector->list obj))) + (else (disp obj)))))) + +(define (display obj . port-list) + (if (null? port-list) + (display obj (current-output-port)) + (let* ((port (car port-list)) + (disp (lambda (str) + (let loop ((index 0)) + (if (< index (string-length str)) + (begin (write-char (string-ref str index) port) + (loop (+ index 1))) + str))))) + + (define (disp-vector vec i) + (if (= i 0) (disp "#(")) + (if (>= i (vector-length vec)) + (disp ")") + (begin (if (not (= 0 i)) (disp " ")) + (display (vector-ref vec i) port) + (disp-vector vec (+ i 1))))) + (define (disp-list prefix l) + (cond ((pair? (cdr l)) + (disp prefix) + (display (car l) port) + (disp-list " " (cdr l))) + ((null? (cdr l)) + (disp prefix) + (display (car l) port) + (disp ")")) + (else + (disp prefix) + (display (car l) port) + (disp " . ") + (display (cdr l) port) + (disp ")")))) + (cond ((string? obj) (disp obj)) + ((symbol? obj) (disp (symbol->string obj))) + ((number? obj) (disp (number->string obj))) + ((boolean? obj) (disp (if obj "#t" "#f"))) + ((char? obj) (write-char obj port)) + ((vector? obj) (disp-vector obj 0)) + ((and (list? obj) (= 2 (length obj)) (eqv? 'quote (car obj))) + (begin (disp "'") (display (cadr obj) port))) + ((pair? obj) (disp-list "(" obj)) + ((null? obj) (disp "()")) + ((procedure? obj) (disp "#")) + ((and (input-port? obj) (output-port? obj)) + (disp "#")) + ((input-port? obj) (disp "#")) + ((output-port? obj) (disp "#")) + ((eof-object? obj) (disp "#")) + ; input port, output port, procedure, continuation, etc. + (else (disp "#")))))) + +(define (newline . port) + (if (null? port) + (newline (current-output-port)) + (display #\newline (car port)))) + +(define (quotient numerator denominator) + (define (sign x) + (cond ((zero? x) + 0) + ((negative? x) + -1) + (else + 1))) + + (define (iter-fast result remainder denominator depth) + (let ((next (* denominator depth))) + (if (< next remainder) + (iter-fast (+ result depth) + (- remainder next) + denominator + next) + (iter-slow result remainder denominator)))) + + (define (iter-slow result remainder denominator) + (if (< remainder denominator) + result + (iter-fast (+ result 1) (- remainder denominator) denominator 1))) + + (let ((result (iter-fast 0 (abs numerator) (abs denominator) 1))) + (if (= (sign numerator) (sign denominator)) + result + (- 0 result)))) + +(define (remainder numerator denominator) + (let ((q (quotient numerator denominator))) + (- numerator (* q denominator)))) + +(define (modulo numerator denominator) + (define (sign x) + (cond ((zero? x) + 0) + ((negative? x) + -1) + (else + 1))) + + (let ((r (remainder numerator denominator))) + (if (= (sign denominator) (sign r)) + r + (+ denominator r)))) + +(define (number->string z . args) + (define chars "0123456789abcdef") + ;; Note that R5RS defines number->string as a procedure and not a + ;; library procedure. However right now we provide only a simple + ;; integer implementation as a library procedure. + (define (iter x result radix) + (if (zero? x) + (if (null? result) + (list->string (list #\0)) + (list->string result)) + (iter (quotient x radix) + (cons (string-ref chars (remainder x radix)) + result) + radix))) + + (define (inner x radix) + (if (and (= x -2147483648) + (= radix 10)) + "-2147483648" + (let ((s (iter (abs x) '() radix))) + (if (negative? x) + (string-append "-" s) + s)))) + + (cond ((null? args) + (inner z 10)) + ((or (not (null? (cdr args))) + (not (integer? (car args))) + (case (car args) + ((2 8 10 16) #f) + (else #t))) + (error "Invalid radix specified" args)) + (else + (inner z (car args))))) + +(define (/ z . args) + (define (iter result args) + (if (null? args) + result + (iter (quotient result (car args)) + (cdr args)))) + + (if (null? args) + (quotient 1 z) + (iter z args))) diff --git a/src/rtl/r5rs-native.scm b/src/rtl/r5rs-native.scm new file mode 100644 index 0000000..59a9cec --- /dev/null +++ b/src/rtl/r5rs-native.scm @@ -0,0 +1,1203 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macros +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define gc-array-mask -2147483648) + +(define '(const 1)) +(define '(const 2)) +(define '(const 3)) +(define `(const ,(+ gc-array-mask 4))) +(define `(const ,(+ gc-array-mask 5))) +(define '(const 6)) +(define '(const 7)) +(define '(const 8)) +(define `(const ,(+ gc-array-mask 9))) +(define '(const 10)) +(define '(const 11)) +(define '(const 12)) +(define '(const 314159)) + +(define (argument-count-check n) + (let* ((token (make-label-token)) + (ok-label (make-label 'argument-count-check token))) + `((assign (reg accum) (op equal-to) (reg index) (const ,n)) + (branch-nonzero (label ,ok-label) (reg accum)) + (assign (reg accum) (const ,n)) + (push (reg accum)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-argument-count-error)) + (label ,ok-label)))) + +(define (predicate-impl tag) + (let* ((token (make-label-token)) + (done-label (make-label 'type-predicate-done token)) + (check-type-label (make-label 'type-predicate-check token)) + ) + `(:enter + ,@(argument-count-check 1) + (assign (reg accum) obj) + (assign (reg accum) (op equal-to) (reg accum) (const 0)) + (branch-zero (label ,check-type-label) (reg accum)) + (assign (reg accum) (label $scmliteral-false)) + (goto (label ,done-label)) + (label ,check-type-label) + (assign (reg accum) obj) + (assign (reg accum) (op load-array) (reg accum) (const 1)) + (assign (reg accum) (op equal-to) (reg accum) ,tag) + (assign (reg operand) (label $scmliteral-boolean)) + (assign (reg accum) (op load-array) (reg operand) (reg accum)) + (label ,done-label) + :leave))) + +;; the code produced by runtime-type-check is allowed use of the accum +;; register. "obj" is the input register which contains a pointer to +;; the associated object to be checked. "tag" is a type tag value of +;; the form "(const N)", which is the required type of the object. +;; If the typecheck fails, the code will terminate the given +;; process. +(define (runtime-type-check obj tag) + (if (equal? tag '(reg accum)) + (error "runtime-type-check: input must not be (reg accum)")) + (let* ((token (make-label-token)) + (ok-label (make-label 'rttc-ok token)) + (err-label (make-label 'rttc-fail token)) + ) + ;; we are only allowed to stomp on (reg accum) in this code. + `((assign (reg accum) ,obj) + (assign (reg accum) (op equal-to) (reg accum) (const 0)) + (branch-nonzero (label ,err-label) (reg accum)) + (assign (reg accum) ,obj) + (assign (reg accum) (op load-array) (reg accum) (const 1)) + (assign (reg accum) (op equal-to) (reg accum) ,tag) + (branch-nonzero (label ,ok-label) (reg accum)) + (label ,err-label) + ;; set up a call to the "ZOMG" function. Notice that this + ;; isn't saving registers because it is not expected to + ;; return. + (assign (reg accum) ,obj) + (push (reg accum)) + (assign (reg accum) ,tag) + (push (reg accum)) + (perform (op call) (label scheme-rtl-runtime-type-error)) + (label ,ok-label)))) + +(define (integer-binary-op-impl op-name) + `( + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'x ) + ,@(runtime-type-check 'y ) + (assign (reg operand) x) + (assign (reg index) (op load-array) (reg operand) (const 0)) + (assign (reg operand) y) + (assign (reg accum) (op load-array) (reg operand) (const 0)) + (assign (reg index) (op ,op-name) (reg index) (reg accum)) + (save (reg index)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg index)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (perform (op store-array) (reg accum) (const 1) ,) + :leave)) + +(define (integer-comparison-op-impl op-name) + `( + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'x ) + ,@(runtime-type-check 'y ) + (assign (reg operand) x) + (assign (reg index) (op load-array) (reg operand) (const 0)) + (assign (reg operand) y) + (assign (reg accum) (op load-array) (reg operand) (const 0)) + (assign (reg index) (op ,op-name) (reg index) (reg accum)) + (assign (reg operand) (label $scmliteral-boolean)) + (assign (reg accum) (op load-array) (reg operand) (reg index)) + :leave)) + +(define (char-comparison-op-impl op-name) + `( + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'char1 ) + ,@(runtime-type-check 'char2 ) + (assign (reg operand) char1) + (assign (reg index) (op load-array) (reg operand) (const 0)) + (assign (reg operand) char2) + (assign (reg accum) (op load-array) (reg operand) (const 0)) + (assign (reg index) (op ,op-name) (reg index) (reg accum)) + (assign (reg operand) (label $scmliteral-boolean)) + (assign (reg accum) (op load-array) (reg operand) (reg index)) + :leave)) + +(define (get-pair-car reg) + `((op load-array) ,reg (const 2))) + +(define (get-pair-cdr reg) + `((op load-array) ,reg (const 3))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Imported symbols +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(emit (extern scheme-rtl-runtime-type-error) + (extern scheme-rtl-runtime-argument-count-error) + (extern scheme-rtl-runtime-bounds-error) + (extern cp-rtl-malloc) + (extern scheme-rtl-close-file-handle) + (extern scheme-rtl-get-stdin-handle) + (extern scheme-rtl-get-stdout-handle) + (extern scheme-rtl-open-input-file-handle) + (extern scheme-rtl-open-output-file-handle) + (extern scheme-rtl-read-byte) + (extern scheme-rtl-write-byte) + (extern scheme-rtl-getenv) + (extern scheme-rtl-strlen) + (extern scheme-rtl-strcpy) + (extern scheme-rtl-mkstring) + (extern scheme-rtl-current-seconds) + (extern scheme-rtl-current-milliseconds) + (extern scheme-rtl-stat-file) + (extern scheme-rtl-delete-file) + (extern scheme-rtl-rename-file) + + (export $scmliteral-unspecified) + (export $scmliteral-true) + (export $scmliteral-false) + (export $scmliteral-boolean) + (export $scmliteral-nil) + (export $scmliteral-eof) + (export $scmliteral-stdin) + (export $scmliteral-stdout) + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Definitions of distinguished RTL objects (nil, true, false, etc.) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(emit (global $scmliteral-true + (const 1) + ,) + (global $scmliteral-false + (const 0) + ,) + (global $scmliteral-boolean + (label $scmliteral-false) + (label $scmliteral-true)) + ) + +(emit (global $scmliteral-nil + (const 0) + , + ) + ) + +(emit (global $scmliteral-eof + (const 0) + ,) + ) + +(emit (global $scmliteral-unspecified + (const 0) + ,) + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Advanced procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (%apply f args) + ,@(argument-count-check 2) + (assign (reg index) (const 0)) + ;; operand := f + (assign (reg operand) (op load-array) (sys stack-pointer) (const 0)) + ,@(runtime-type-check '(reg operand) ) + ;; pointer := args + (assign (reg pointer) (op load-array) (sys stack-pointer) (const 1)) + ;; pop args off the stack + (assign (sys stack-pointer) (op add-pointer) (sys stack-pointer) (const 2)) + ;; this := head-of-list + (assign (reg this) (reg pointer)) + ;; loop to count arguments + (label %apply/begin-count) + (assign (reg accum) (op equal-to) (reg this) (label $scmliteral-nil)) + (branch-nonzero (label %apply/count-done) (reg accum)) + (assign (reg index) (op add) (reg index) (const 1)) + ;; this := cdr(this) + ,@(runtime-type-check '(reg this) ) + (assign (reg this) (op load-array) (reg this) (const 3)) + (goto (label %apply/begin-count)) + (label %apply/count-done) + ;; reserve space on the stack for the arguments. index holds the number of + ;; arguments, we need to shift this to multiply by the size of a pointer. + (assign (reg index) (op bit-lshift) (reg index) (symconst shift-cells-per-word)) + (assign (sys stack-pointer) (op sub) (sys stack-pointer) (reg index)) + (assign (reg index) (op bit-rshift) (reg index) (symconst shift-cells-per-word)) + ;; pop the pointer to the head of the list back into accum, then copy those + ;; arguments into the stack + (assign (reg this) (sys stack-pointer)) + (label %apply/begin-copy-args) + (assign (reg accum) (op equal-to) (reg pointer) (label $scmliteral-nil)) + (branch-nonzero (label %apply/copy-args-done) (reg accum)) + ;; accum := car(pointer) + (assign (reg accum) (op load-array) (reg pointer) (const 2)) + (perform (op store-array) (reg this) (const 0) (reg accum)) + ;; pointer := cdr(pointer) + (assign (reg pointer) (op load-array) (reg pointer) (const 3)) + (assign (reg this) (op add-pointer) (reg this) (const 1)) + (goto (label %apply/begin-copy-args)) + (label %apply/copy-args-done) + ;; args are copied, index is set, stack pointer is correct. + ;; function pointer is in operand, set the env register and jump to it + (assign (reg this) (op load-array) (reg operand) (const 2)) + (assign (reg operand) (op load-array) (reg operand) (const 3)) + (goto (reg operand))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Character Procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (char->integer char) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'char ) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (assign (reg operand) char) + (assign (reg operand) (op load-array) (reg operand) (const 0)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) (const 1)) + :leave) + +(define-glue (integer->char int) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'int ) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (assign (reg operand) int) + (assign (reg operand) (op load-array) (reg operand) (const 0)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) (const 3)) + :leave) + +(define-glue (char<=? char1 char2) + ,@(char-comparison-op-impl 'less-than-or-equal) + ) + +(define-glue (char) + (branch-nonzero (label eqv?/process-integer) (reg accum)) + ;; not an integer. character? + (assign (reg accum) (op equal-to) (reg operand) ,) + (branch-zero (label eqv?/check-symbol) (reg accum)) + (label eqv?/process-integer) + ;; this is either an integer or a character. They have similar + ;; layout and semantics, so we process them with the same code. + (assign (reg accum) obj-a) + (assign (reg operand) obj-b) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (assign (reg operand) (op load-array) (reg operand) (const 0)) + (assign (reg accum) (op equal-to) (reg accum) (reg operand)) + ;; we've got accum equal to 0 if they are equal and 1 otherwise. use this + ;; value to index into $scmliteral-boolean. + (assign (reg accum) (op load-array) (label $scmliteral-boolean) (reg accum)) + (goto (label eqv?/done)) + (label eqv?/check-symbol) + ;; this is neither an integer or a character. symbol? + (assign (reg accum) (op equal-to) (reg operand) ,) + (branch-nonzero (label eqv?/process-symbol) (reg accum)) + ;; not a symbol. Well, these two aren't equivalent. + (assign (reg accum) (label $scmliteral-false)) + (goto (label eqv?/done)) + (label eqv?/process-symbol) + ;; this is a symbol. Let's do a strcmp. Check the lengths first. + (assign (reg accum) obj-a) + (assign (reg operand) obj-b) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (assign (reg operand) (op load-array) (reg operand) (const 0)) + ;; accum is the length of a, operand the length of b. + (assign (reg index) (op equal-to) (reg accum) (reg operand)) + (branch-nonzero (label eqv?/compare-symbols) (reg index)) + ;; the lengths aren't equal so these aren't equal symbols. + (assign (reg accum) (label $scmliteral-false)) + (goto (label eqv?/done)) + (label eqv?/compare-symbols) + (assign (reg accum) obj-a) + (assign (reg operand) obj-b) + (assign (reg index) (op load-array) (reg accum) (const 0)) + (assign (reg pointer) (op add-pointer) (reg accum) (const 2)) + (assign (reg operand) (op add-pointer) (reg operand) (const 2)) + (label eqv?/compare-symbols-loop) + (branch-nonzero (label eqv?/compare-symbols-iter) (reg index)) + ;; we got to the end of the symbol names. they must be equal. + (assign (reg accum) (label $scmliteral-true)) + (goto (label eqv?/done)) + (label eqv?/compare-symbols-iter) + (assign (reg accum) (op load-array) (reg pointer) (const 0)) + (assign (reg this) (op load-array) (reg operand) (const 0)) + (assign (reg accum) (op equal-to) (reg accum) (reg this)) + (branch-nonzero (label eqv?/symbols-next-char) (reg accum)) + ;; the characters weren't equal, so bail out. + (assign (reg accum) (label $scmliteral-false)) + (goto (label eqv?/done)) + (label eqv?/symbols-next-char) + ;; the characters were equal, so set up for the next iteration + (assign (reg pointer) (op add-pointer) (reg pointer) (const 1)) + (assign (reg operand) (op add-pointer) (reg operand) (const 1)) + (assign (reg index) (op sub) (reg index) (const 1)) + (goto (label eqv?/compare-symbols-loop)) + (label eqv?/done) + :leave) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Pair Procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (cons car cdr) + :enter + ,@(argument-count-check 2) + (push (const 4)) + (perform (op call) (label cp-rtl-malloc)) + (perform (op store-array) (reg accum) (const 0) (const 2)) + (perform (op store-array) (reg accum) (const 1) (const ,(+ gc-array-mask 4))) + (perform (op store-array) (reg accum) (const 2) car) + (perform (op store-array) (reg accum) (const 3) cdr) + :leave) + +(define-glue (car pair) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'pair ) + (assign (reg accum) pair) + (assign (reg accum) ,@(get-pair-car '(reg accum))) + :leave) + +(define-glue (cdr pair) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'pair ) + (assign (reg accum) pair) + (assign (reg accum) ,@(get-pair-cdr '(reg accum))) + :leave) + +(define-glue (set-car! pair obj) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'pair ) + (assign (reg accum) pair) + (assign (reg operand) obj) + (perform (op store-array) (reg accum) (const 2) (reg operand)) + (assign (reg accum) (label $scmliteral-unspecified)) + :leave) + +(define-glue (set-cdr! pair obj) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'pair ) + (assign (reg accum) pair) + (assign (reg operand) obj) + (perform (op store-array) (reg accum) (const 3) (reg operand)) + (assign (reg accum) (label $scmliteral-unspecified)) + :leave) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; String Procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (%make-string k char) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'k ) + ,@(runtime-type-check 'char ) + ;; get the string length + (assign (reg accum) k) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + ;; add 3, for the GCDW, array length and NUL terminator + (assign (reg accum) (op add) (reg accum) (const 2)) + ;; call malloc + (push (reg accum)) + (perform (op call) (label cp-rtl-malloc)) + ;; write the header information into the string + (assign (reg index) k) + (assign (reg index) (op load-array) (reg index) (const 0)) + ;; length + (perform (op store-array) (reg accum) (const 0) (reg index)) + ;; string type tag + (perform (op store-array) (reg accum) (const 1) (const 6)) + (branch-zero (label %make-string/write-done) (reg index)) + ;; write the character into the string buffer + (assign (reg operand) char) + (assign (reg operand) (op load-array) (reg operand) (const 0)) + (assign (reg pointer) (op add-pointer) (reg accum) (const 2)) + (label %make-string/write-loop) + (assign (reg index) (op sub) (reg index) (const 1)) + (perform (op store-array) (reg pointer) (const 0) (reg operand)) + (assign (reg pointer) (op add-pointer) (reg pointer) (const 1)) + (branch-nonzero (label %make-string/write-loop) (reg index)) + (label %make-string/write-done) + :leave) + +(define-glue (string->symbol str) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'str ) + ;; calculate required buffer size: length + 2 + (assign (reg accum) str) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (assign (reg accum) (op add) (reg accum) (const 2)) + ;; allocate buffer + (push (reg accum)) + (perform (op call) (label cp-rtl-malloc)) + ;; write header information + (assign (reg pointer) str) + (assign (reg index) (op load-array) (reg pointer) (const 0)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (perform (op store-array) (reg accum) (const 1) (const 7)) + ;; copy buffer + (assign (reg this) (reg accum)) + (assign (reg this) (op add-pointer) (reg this) (const 2)) + (assign (reg pointer) (op add-pointer) (reg pointer) (const 2)) + (label string->symbol/copy-buffer) + (assign (reg index) (op sub) (reg index) (const 1)) + (assign (reg operand) (op load-array) (reg pointer) (reg index)) + (perform (op store-array) (reg this) (reg index) (reg operand)) + (branch-nonzero (label string->symbol/copy-buffer) (reg index)) + (label string->symbol/done) + :leave) + +(define-glue (string-length str) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'str ) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (assign (reg operand) str) + (assign (reg index) (op load-array) (reg operand) (const 0)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (perform (op store-array) (reg accum) (const 1) (const 1)) + :leave) + +(define-glue (string-ref str idx) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'str ) + ,@(runtime-type-check 'idx ) + + (assign (reg this) str) + + ; bounds check + (assign (reg operand) (op load-array) (reg this) (const 0)) ; unbox string length + (assign (reg index) idx) ; unbox integer arg + (assign (reg index) (op load-array) (reg index) (const 0)) + (assign (reg accum) (op less-than) (reg index) (reg operand)) + (branch-nonzero (label string-ref/less-than) (reg accum)) + + ; report error + (push (const 1)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label string-ref/less-than) + (branch-nonzero (label string-ref/greater-than) (result (op greater-than) (reg index) (const -1))) + + ; report error + (push (const 2)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label string-ref/greater-than) + + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (assign (reg index) idx) + (assign (reg index) (op load-array) (reg index) (const 0)) + (assign (reg operand) str) + (assign (reg this) (op add-pointer) (reg operand) (const 2)) + (assign (reg operand) (op load-array) (reg this) (reg index)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) ,) + :leave) + +(define-glue (string-set! str idx c) + :enter + ,@(argument-count-check 3) + ,@(runtime-type-check 'str ) + ,@(runtime-type-check 'idx ) + ,@(runtime-type-check 'c ) + + (assign (reg this) str) + + ; bounds check + (assign (reg operand) (op load-array) (reg this) (const 0)) ; unbox string length + (assign (reg index) idx) ; unbox integer arg + (assign (reg index) (op load-array) (reg index) (const 0)) + (assign (reg accum) (op less-than) (reg index) (reg operand)) + (branch-nonzero (label string-set!/less-than) (reg accum)) + + ; report error + (push (const 1)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label string-set!/less-than) + (branch-nonzero (label string-set!/greater-than) (result (op greater-than) (reg index) (const -1))) + + ; report error + (push (const 2)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label string-set!/greater-than) + + (assign (reg index) idx) + (assign (reg index) (op load-array) (reg index) (const 0)) + (assign (reg operand) c) + (assign (reg operand) (op load-array) (reg operand) (const 0)) + (assign (reg this) str) + (assign (reg this) (op add-pointer) (reg this) (const 2)) + (perform (op store-array) (reg this) (reg index) (reg operand)) + (assign (reg accum) (label $scmliteral-unspecified)) + :leave) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Symbol Procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (symbol->string sym) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'sym ) + ;; calculate required buffer size: length + 2 + (assign (reg accum) sym) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (assign (reg accum) (op add) (reg accum) (const 2)) + ;; allocate buffer + (push (reg accum)) + (perform (op call) (label cp-rtl-malloc)) + ;; write header information + (assign (reg pointer) sym) + (assign (reg index) (op load-array) (reg pointer) (const 0)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (perform (op store-array) (reg accum) (const 1) (const 6)) + ;; copy buffer + (assign (reg this) (reg accum)) + (assign (reg this) (op add-pointer) (reg this) (const 2)) + (assign (reg pointer) (op add-pointer) (reg pointer) (const 2)) + (label symbol->string/copy-buffer) + (assign (reg index) (op sub) (reg index) (const 1)) + (assign (reg operand) (op load-array) (reg pointer) (reg index)) + (perform (op store-array) (reg this) (reg index) (reg operand)) + (branch-nonzero (label symbol->string/copy-buffer) (reg index)) + (label symbol->string/done) + :leave) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Type Predicates +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (number? obj) + ,@(predicate-impl )) + +(define-glue (char? obj) + ,@(predicate-impl )) + +(define-glue (pair? obj) + ,@(predicate-impl )) + +(define-glue (vector? obj) + ,@(predicate-impl )) + +(define-glue (string? obj) + ,@(predicate-impl )) + +(define-glue (symbol? obj) + ,@(predicate-impl )) + +(define-glue (procedure? obj) + ,@(predicate-impl )) + +(define-glue (input-port? obj) + ,@(predicate-impl )) + +(define-glue (output-port? obj) + ,@(predicate-impl )) + +(define-glue (eof-object? obj) + ,@(predicate-impl )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Arithmetic Procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (%- x y) + ,@(integer-binary-op-impl 'sub)) + +(define-glue (%* x y) + ,@(integer-binary-op-impl 'mul)) + +(define-glue (%+ x y) + ,@(integer-binary-op-impl 'add)) + +(define-glue (%= x y) + ,@(integer-comparison-op-impl 'equal-to)) + +(define-glue (%< x y) + ,@(integer-comparison-op-impl 'less-than)) + +(define-glue (%<= x y) + ,@(integer-comparison-op-impl 'less-than-or-equal)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Vector Procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +(define-glue (%make-vector k value) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'k ) + (assign (reg index) k) + (assign (reg index) (op load-array) (reg index) (const 0)) + (assign (reg operand) value) + (assign (reg accum) (op add) (reg index) (const 2)) + (save (reg index)) + (save (reg operand)) + (push (reg accum)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg operand)) + (restore (reg index)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (perform (op store-array) (reg accum) (const 1) ,) + (save (reg accum)) + (assign (reg accum) (op add-pointer) (reg accum) (const 2)) + (label %make-vector/begin-loop) + (branch-zero (label %make-vector/end-loop) (reg index)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (assign (reg accum) (op add-pointer) (reg accum) (const 1)) + (assign (reg index) (op sub) (reg index) (const 1)) + (goto (label %make-vector/begin-loop)) + (label %make-vector/end-loop) + (restore (reg accum)) + :leave) + + +(define-glue (vector-length vec) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'vec ) + (assign (reg accum) vec) + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (save (reg operand)) + (assign (reg accum) (const 2)) + (push (reg accum)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg operand)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) ,) + :leave) + + +(define-glue (vector-ref vec k) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'vec ) + ,@(runtime-type-check 'k ) + (assign (reg this) vec) + ; bounds check + (assign (reg operand) (op load-array) (reg this) (const 0)) ; unbox vector length + (assign (reg index) k) ; unbox integer arg + (assign (reg index) (op load-array) (reg index) (const 0)) + (assign (reg accum) (op less-than) (reg index) (reg operand)) + (branch-nonzero (label vector-ref/less-than) (reg accum)) + + ; report error + (push (const 1)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label vector-ref/less-than) + (branch-nonzero (label vector-ref/greater-than) (result (op greater-than) (reg index) (const -1))) + + ; report error + (push (const 2)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label vector-ref/greater-than) + ; move past vector header + (assign (reg accum) (op add-pointer) (reg this) (const 2)) + ; reference vector + (assign (reg accum) (op load-array) (reg accum) (reg index)) + :leave) + + +(define-glue (vector-set! vec k obj) + :enter + ,@(argument-count-check 3) + ,@(runtime-type-check 'vec ) + ,@(runtime-type-check 'k ) + + (assign (reg this) vec) + ; bounds check + (assign (reg operand) (op load-array) (reg this) (const 0)) ; unbox vector length + (assign (reg index) k) ; unbox integer arg + (assign (reg index) (op load-array) (reg index) (const 0)) + (assign (reg accum) (op less-than) (reg index) (reg operand)) + (branch-nonzero (label vector-set!/less-than) (reg accum)) + + ; report error + (push (const 3)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label vector-set!/less-than) + (branch-nonzero (label vector-set!/greater-than) (result (op greater-than) (reg index) (const -1))) + + ; report error + (push (const 4)) + (push (reg operand)) + (push (reg index)) + (perform (op call) (label scheme-rtl-runtime-bounds-error)) + (perform (op break)) + + (label vector-set!/greater-than) + ; move past vector header + (assign (reg accum) (op add-pointer) (reg this) (const 2)) + + ; set vector element + (assign (reg operand) obj) + (perform (op store-array) (reg accum) (reg index) (reg operand)) + (assign (reg accum) (label $scmliteral-unspecified)) + + :leave) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; I/O Procedures +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-glue (close-input-port port) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'port ) + (assign (reg accum) port) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (push (reg accum)) + (perform (op call) (label scheme-rtl-close-file-handle)) + (assign (reg accum) (label $scmliteral-unspecified)) + :leave) + +(define-glue (close-output-port port) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'port ) + (assign (reg accum) port) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (push (reg accum)) + (perform (op call) (label scheme-rtl-close-file-handle)) + (assign (reg accum) (label $scmliteral-unspecified)) + :leave) + +(emit (global $scmliteral-stdin + (const 0) + ,)) + +(emit (global $scmliteral-stdout + (const 0) + ,)) + +(define-glue (current-input-port) + :enter + ,@(argument-count-check 0) + (assign (reg accum) (label $scmliteral-stdin)) + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (assign (reg operand) (op equal-to) (reg operand) (const 0)) + (branch-zero (label current-input-port/done) (reg operand)) + (perform (op call) (label scheme-rtl-get-stdin-handle)) + (assign (reg operand) (label $scmliteral-stdin)) + (perform (op store-array) (reg operand) (const 0) (reg accum)) + (assign (reg accum) (reg operand)) + (label current-input-port/done) + :leave) + +(define-glue (current-output-port) + :enter + ,@(argument-count-check 0) + (assign (reg accum) (label $scmliteral-stdout)) + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (assign (reg operand) (op equal-to) (reg operand) (const 0)) + (branch-zero (label current-output-port/done) (reg operand)) + (perform (op call) (label scheme-rtl-get-stdout-handle)) + (assign (reg operand) (label $scmliteral-stdout)) + (perform (op store-array) (reg operand) (const 0) (reg accum)) + (assign (reg accum) (reg operand)) + (label current-output-port/done) + :leave) + +(define-glue (open-input-file fname) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'fname ) + (assign (reg operand) fname) + ;; arg 1 - string length + (assign (reg accum) (op load-array) (reg operand) (const 0)) + (push (reg accum)) + ;; arg 0 - string pointer + (assign (reg accum) (op add-pointer) (reg operand) (const 2)) + (push (reg accum)) + (perform (op call) (label scheme-rtl-open-input-file-handle)) + + (assign (reg operand) (reg accum)) + (save (reg operand)) + (push (const 4)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg operand)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) ,) + (assign (reg operand) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 2) (reg operand)) + :leave) + + +(define-glue (open-output-file fname) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'fname ) + (assign (reg operand) fname) + ;; arg 1 - string length + (assign (reg accum) (op load-array) (reg operand) (const 0)) + (push (reg accum)) + ;; arg 0 - string pointer + (assign (reg accum) (op add-pointer) (reg operand) (const 2)) + (push (reg accum)) + (perform (op call) (label scheme-rtl-open-output-file-handle)) + + (assign (reg operand) (reg accum)) + (save (reg operand)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg operand)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) ,) + :leave) + +(define-glue (%peek-char port) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'port ) + (assign (reg operand) port) + (assign (reg accum) (op load-array) (reg operand) (const 2)) + (assign (reg index) (op equal-to) (reg accum) (label $scmliteral-false)) + (assign (reg accum) (op load-array) (reg operand) (const 3)) + (branch-nonzero (label %peek-char-proceed) (reg index)) + (goto (label %peek-char-read)) + (label %peek-char-proceed) + (assign (reg accum) (op load-array) (reg operand) (const 0)) + (push (reg accum)) + (perform (op call) (label scheme-rtl-read-byte)) + (assign (reg operand) port) + (perform (op store-array) (reg operand) (const 2) (label $scmliteral-true)) + (perform (Op store-array) (reg operand) (const 3) (reg accum)) + (label %peek-char-read) + (assign (reg operand) (op less-than) (reg accum) (const 0)) + (branch-zero (label %peek-char-regular-char) (reg operand)) + (assign (reg accum) (label $scmliteral-eof)) + (goto (label %peek-char-done)) + (label %peek-char-regular-char) + (assign (reg operand) (reg accum)) + (save (reg operand)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg operand)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) ,) + (label %peek-char-done) + :leave) + +(define-glue (%read-char port) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'port ) + (assign (reg operand) port) + (assign (reg accum) (op load-array) (reg operand) (const 2)) + (assign (reg index) (op equal-to) (reg accum) (label $scmliteral-false)) + (assign (reg accum) (op load-array) (reg operand) (const 3)) + (branch-nonzero (label %read-char-proceed) (reg index)) + + (assign (reg index) (label $scmliteral-false)) + (perform (op store-array) (reg operand) (const 2) (reg index)) + (assign (reg accum) (op load-array) (reg operand) (const 3)) + (goto (label %read-char-byte-already-read)) + + (label %read-char-proceed) + (assign (reg accum) (op load-array) (reg operand) (const 0)) + (push (reg accum)) + (perform (op call) (label scheme-rtl-read-byte)) + + (label %read-char-byte-already-read) + (assign (reg operand) (op less-than) (reg accum) (const 0)) + (branch-zero (label %read-char-regular-char) (reg operand)) + + (assign (reg accum) (label $scmliteral-eof)) + (goto (label %read-char-done)) + + (label %read-char-regular-char) + (assign (reg operand) (reg accum)) + (save (reg operand)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg operand)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + (perform (op store-array) (reg accum) (const 1) ,) + + (label %read-char-done) + :leave) + +(define-glue (%write-char char port) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'char ) + ,@(runtime-type-check 'port ) + (assign (reg accum) port) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (push (reg accum)) + (assign (reg accum) char) + (assign (reg accum) (op load-array) (reg accum) (const 0)) + (push (reg accum)) + (perform (op call) (label scheme-rtl-write-byte)) + (assign (reg accum) (label $scmliteral-unspecified)) + :leave) + +(define-glue (getenv var) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'var ) + + ;; push arg1 = length + (assign (reg accum) var) + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (push (reg operand)) + ;; push arg0 = string pointer + (assign (reg operand) (op add-pointer) (reg accum) (const 2)) + (push (reg operand)) + ;; call + (perform (op call) (label scheme-rtl-getenv)) + + (branch-nonzero (label getenv/false) (reg accum)) + (assign (reg accum) (label $scmliteral-false)) + (goto (label getenv/done)) + + (label getenv/false) + (push (reg accum)) + (perform (op call) (label scheme-rtl-mkstring)) + + (label getenv/done) + :leave) + +(define-glue (stat path) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'path ) + + ;; + ;; allocate a vector of 10 elements + ;; + (push (const 12)) + (perform (op call) (label cp-rtl-malloc)) + (perform (op store-array) (reg accum) (const 0) (const 10)) + (perform (op store-array) (reg accum) (const 1) ,) + (perform (op store-array) (reg accum) (const 2) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 3) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 4) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 5) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 6) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 7) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 8) (label $scmliteral-false)) + ;(perform (op store-array) (reg accum) (const 9) (label $scmliteral-false)) + (perform (op store-array) (reg accum) (const 10) (label $scmliteral-false)) + ;(perform (op store-array) (reg accum) (const 11) (label $scmliteral-false)) + + (save (reg accum)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (perform (op store-array) (reg accum) (const 0) (const 0)) + (perform (op store-array) (reg accum) (const 1) ,) + (restore (reg operand)) + (perform (op store-array) (reg operand) (const 9) (reg accum)) + + (save (reg operand)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (perform (op store-array) (reg accum) (const 0) (const 0)) + (perform (op store-array) (reg accum) (const 1) ,) + (restore (reg operand)) + (perform (op store-array) (reg operand) (const 11) (reg accum)) + + (assign (reg accum) (reg operand)) + (save (reg accum)) + + ;; push arg3 = vector length + (push (const 10)) + ;; push arg2 = vector buffer pointer + (assign (reg accum) (op add-pointer) (reg accum) (const 2)) + (push (reg accum)) + ;; push arg1 = string length + (assign (reg accum) path) + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (push (reg operand)) + ;; push arg0 = string buffer pointer + (assign (reg operand) (op add-pointer) (reg accum) (const 2)) + (push (reg operand)) + ;; call + (perform (op call) (label scheme-rtl-stat-file)) + + (branch-nonzero (label stat/failed) (reg accum)) + (restore (reg accum)) + (goto (label stat/done)) + + (label stat/failed) + (assign (reg accum) (label $scmliteral-false)) + + (label stat/done) + :leave) + +(define-glue (current-seconds) + :enter + (perform (op call) (label scheme-rtl-current-seconds)) + (save (reg accum)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg index)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (perform (op store-array) (reg accum) (const 1) ,) + :leave) + +(define-glue (current-milliseconds) + :enter + (perform (op call) (label scheme-rtl-current-milliseconds)) + (save (reg accum)) + (push (const 2)) + (perform (op call) (label cp-rtl-malloc)) + (restore (reg index)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (perform (op store-array) (reg accum) (const 1) ,) + :leave) + +(define-glue (delete-file path) + :enter + ,@(argument-count-check 1) + ,@(runtime-type-check 'path ) + + (assign (reg accum) path) + ;; push arg1 = length + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (push (reg operand)) + ;; push arg0 = buffer pointer + (assign (reg accum) (op add-pointer) (reg accum) (const 2)) + (push (reg accum)) + ;; call + (perform (op call) (label scheme-rtl-delete-file)) + + ;; assign correct result object + (branch-nonzero (label delete-file/failed) (reg accum)) + (assign (reg accum) (label $scmliteral-true)) + (goto (label delete-file/done)) + + (label delete-file/failed) + (assign (reg accum) (label $scmliteral-false)) + + (label delete-file/done) + :leave) + +(define-glue (rename-file from to) + :enter + ,@(argument-count-check 2) + ,@(runtime-type-check 'from ) + ,@(runtime-type-check 'to ) + + (assign (reg accum) to) + ;; push arg3 = length + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (push (reg operand)) + ;; push arg2 = buffer pointer + (assign (reg accum) (op add-pointer) (reg accum) (const 2)) + (push (reg accum)) + + (assign (reg accum) from) + ;; push arg1 = length + (assign (reg operand) (op load-array) (reg accum) (const 0)) + (push (reg operand)) + ;; push arg0 = buffer pointer + (assign (reg accum) (op add-pointer) (reg accum) (const 2)) + (push (reg accum)) + + ;; call + (perform (op call) (label scheme-rtl-rename-file)) + + ;; assign correct result object + (branch-nonzero (label rename-file/failed) (reg accum)) + (assign (reg accum) (label $scmliteral-true)) + (goto (label rename-file/done)) + + (label rename-file/failed) + (assign (reg accum) (label $scmliteral-false)) + + (label rename-file/done) + :leave) diff --git a/src/rtl/r5rs-syntax.scm b/src/rtl/r5rs-syntax.scm new file mode 100644 index 0000000..33db983 --- /dev/null +++ b/src/rtl/r5rs-syntax.scm @@ -0,0 +1,206 @@ +(define-syntax quasiquote + (syntax-rules (unquote unquote-splicing) + ((_ (unquote )) + ) + ((_ ((unquote-splicing ) ...)) + (append + (quasiquote ( ...)))) + ((_ ( ...)) + (cons (quasiquote ) + (quasiquote ( ...)))) + ((_ ) + (quote )))) + +(define-syntax and + (syntax-rules () + ((_) + #t) + ((_ ) + ) + ((_ ...) + (if + (and ...) + #f)))) + +(define-syntax or + (syntax-rules () + ((_) + #f) + ((_ ) + ) + ((_ ...) + (let ((res )) + (if res + res + (or ...)))))) + +(define-syntax let + (syntax-rules () + ((let ((name val) ...) body1 body2 ...) + ((lambda (name ...) body1 body2 ...) + val ...)) + ((let tag ((name val) ...) body1 body2 ...) + (letrec ((tag (lambda (name ...) + body1 body2 ...))) + (tag val ...))))) + +; Original named-let implementation, seemed slightly sub-optimal: +; ((let tag ((name val) ...) body1 body2 ...) +; ((letrec ((tag (lambda (name ...) +; body1 body2 ...))) +; tag) +; val ...)))) + +(define-syntax let* + (syntax-rules () + ((let* () body1 body2 ...) + (let () body1 body2 ...)) + ((let* ((name1 val1) (name2 val2) ...) + body1 body2 ...) + (let ((name1 val1)) + (let* ((name2 val2) ...) + body1 body2 ...))))) + +;; LETREC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Two versions of letrec macros are given below in comments. The +;; version from Al Petrofsky is considered more compliant with the +;; wording in R5RS. Neither is used because neither is convenient +;; for recognition by the optimizer or code generator. Instead, +;; letrec is considered a special form. + +; letrec from Al Petrofsky +;(define-syntax letrec +; (syntax-rules () +; ((_ ((var init) ...) . body) +; (let ((var 0) ...) ;; todo: switch to 'undefined +; (let ((var (let ((temp init)) (lambda () (set! var temp)))) +; ... +; (bod (lambda () . body))) +; (var) ... (bod)))))) + +; letrec from R5RS +;(define-syntax letrec +; (syntax-rules () +; ((letrec ((var1 init1) ...) body ...) +; (letrec "generate_temp_names" +; (var1 ...) +; () +; ((var1 init1) ...) +; body ...)) +; ((letrec "generate_temp_names" +; () +; (temp1 ...) +; ((var1 init1) ...) +; body ...) +; (let ((var1 ') ...) +; (let ((temp1 init1) ...) +; (set! var1 temp1) +; ... +; body ...))) +; ((letrec "generate_temp_names" +; (x y ...) +; (temp ...) +; ((var1 init1) ...) +; body ...) +; (letrec "generate_temp_names" +; (y ...) +; (newtemp temp ...) +; ((var1 init1) ...) +; body ...)))) + +;(define-syntax begin +; (syntax-rules () +; ((begin) +; (if #f #f)) +; ((begin exp) +; exp) +; ((begin exp1 exp2 ...) +; (let ((x exp1)) +; (begin exp2 ...))))) + +(define-syntax cond + (syntax-rules (else =>) + ((cond (else ...)) + (begin ...)) + ((cond ( => ) ...) + (let ((temp )) + (if temp + ( temp) + (cond ...)))) + ((cond ()) + ) + ((cond () ...) + (let ((temp )) + (if temp + temp + (cond ...)))) + ((cond ( ...)) + (if + (begin ...))) + ((cond ( ...) + ...) + (if + (begin ...) + (cond ...))))) + +(define-syntax case + (syntax-rules (else) +; ((case (key ...) +; clauses ...) +; (let ((atom-key (key ...))) +; (case atom-key clauses ...))) + ((case key + (else result1 result2 ...)) + (begin result1 result2 ...)) + ((case key + ((atoms ...) result1 result2 ...) + clause clauses ...) + (if (memv key '(atoms ...)) + (begin result1 result2 ...) + (case key clause clauses ...))) + ((case key + ((atoms ...) result1 result2 ...)) + (if (memv key '(atoms ...)) + (begin result1 result2 ...))))) + +(define-syntax do + (syntax-rules () + ((do ((var init step ...) ...) + (test expr ...) + command ...) + (letrec + ((loop + (lambda (var ...) + (if test + (begin + (if #f #f) + expr ...) + (begin + command + ... + (loop (do "step" var step ...) + ...)))))) + (loop init ...))) + ((do "step" x) + x) + ((do "step" x y) + y))) + + (define-syntax delay + (syntax-rules () + ((delay ) + ((lambda (proc) + (let ((result-ready? #f) + (result #f)) + (lambda () + (if result-ready? + result + (let ((x (proc))) + (if result-ready? + result + (begin (set! result-ready? #t) + (set! result x) + result))))))) + (lambda () ))))) + diff --git a/src/rtl/r5rs-wrap.scm b/src/rtl/r5rs-wrap.scm new file mode 100644 index 0000000..e2902a9 --- /dev/null +++ b/src/rtl/r5rs-wrap.scm @@ -0,0 +1,502 @@ +;; r5rs-wrap.scm +;; Definitions of R5RS procedures in terms of %-prefixed intrinsic operations. + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ADVANCED ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (apply proc arg1 ... args) + +(define (apply f . args) + (if (null? (cdr args)) + (%apply f (car args)) + (let loop ((prev args) + (curr (cdr args))) + (if (null? (cdr curr)) + (begin (set-cdr! prev (car curr)) + (%apply f args)) + (loop curr (cdr curr)))))) + +;; [[procedure]] (call-with-current-continuation proc) +;; [[procedure]] (call-with-values producer consumer) +;; [[procedure]] (dynamic-wind before thunk after) +;; [[procedure]] (eval expression environment-specifier) +;; [[procedure]] (null-environment version) +;; [[procedure]] (scheme-report-environment version) +;; [[procedure]] (values obj ...) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; CHARACTERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (char->integer char) +;; [[procedure]] (char<=? char1 char2) +;; [[procedure]] (char=? char1 char2) +;; [[procedure]] (char>? char1 char2) +;; [[procedure]] (integer->char n) + +(define (char>=? char1 char2) + (not (char? char1 char2) + (not (char<=? char1 char2))) + +;; (other char procedures implemented in SASM, see r5rs-native.scm) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; EQUIVALENCE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (eq? obj1 obj2) +;; [[procedure]] (eqv? obj1 obj2) + +;; implemented in raw SASM, see r5rs-native.scm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PAIRS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (car pair) +;; [[procedure]] (cdr pair) +;; [[procedure]] (cons obj1 obj2) +;; [[procedure]] (set-car! pair obj) +;; [[procedure]] (set-cdr! pair obj) + +;; implemented in raw SASM, see r5rs-native.scm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; STRINGS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (make-string k char) +;; [[procedure]] (make-string k) + +(define (make-string k . args) + (if (null? args) + (%make-string k #\space) + (%make-string k (car args)))) + +;; [[procedure]] (string->number string radix) +;; [[procedure]] (string->number string) + +(define (string->number string . args) + (define (helper radix) + (let ((chars "0123456789abcdef") + (alt-chars "0123456789ABCDEF")) + (define (value-of x) + (let loop ((i 0)) + (cond ((>= i radix) + #f) + ((or (char=? (string-ref chars i) x) + (char=? (string-ref alt-chars i) x)) + i) + (else + (loop (+ i 1)))))) + (define (check-overflow? i result) + (not (and (= radix 16) + (<= i 8)))) + (define (iter idx result) + (if (= idx (string-length string)) + result + (if (< result 0) + #f + (let ((next (value-of (string-ref string idx)))) + (if next + (let* ((operand (* result radix)) + (next-result (+ operand next))) + (if (and (check-overflow? idx result) + (or (< operand 0) + (< next-result 0) + (< next-result operand)) + ) + #f ; overflow + (iter (+ idx 1) (+ operand next)) + ) + ) + next))))) + (if (= (string-length string) 0) + #f + (if (char=? (string-ref string 0) #\-) + (if (= (string-length string) 1) + #f + (if (and (= radix 10) + ; due to parsing as positive, and 32-bit + ; limit, INT_MIN is special-cased, since it + ; can't be represented directly as a + ; positive number + (string=? "-2147483648" string)) + (- -2147483647 1) + (let ((res (iter 1 0))) + (if res (- 0 res) res)))) + (iter 0 0))))) + + (cond ((= 0 (string-length string)) + #f) + ((null? args) + (helper 10)) + (else + (helper (car args))))) + +;; [[procedure]] (string->symbol string) +;; [[procedure]] (string-length string) +;; [[procedure]] (string-ref string k) +;; [[procedure]] (string-set! string k char) + +;; implemented in raw SASM, see r5rs-native.scm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; SYMBOLS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (symbol->string symbol) + +;; implemented in raw SASM, see r5rs-native.scm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; TYPE PREDICATES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (char? obj) +;; [[procedure]] (input-port? obj) +;; [[procedure]] (number? obj) +;; [[procedure]] (output-port? obj) +;; [[procedure]] (pair? obj) +;; [[procedure]] (procedure? obj) +;; [[procedure]] (string? obj) +;; [[procedure]] (symbol? obj) +;; [[procedure]] (vector? obj) + +;; implemented in raw SASM, see r5rs-native.scm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; VECTORS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (make-vector k fill) +;; [[procedure]] (make-vector k) +;; [[procedure]] (vector-length vector) +;; [[procedure]] (vector-ref vector k) +;; [[procedure]] (vector-set! vector k obj) + +(define (make-vector k . args) + (if (null? args) + (%make-vector k '()) + (%make-vector k (car args)))) + +;; implemented in raw SASM, see r5rs-native.scm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NUMERICS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (/ z) +;; [[procedure]] (/ z1 z2) +;; [[procedure]] (> x1 x2 x3 ...) +;; [[procedure]] (>= x1 x2 x3 ...) + +;; partially implemented in r5rs-native.sasm +;; [[procedure]] (* z1 ...) +;; [[procedure]] (+ z1 ...) +;; [[procedure]] (- z) +;; [[procedure]] (- z1 z2) +;; [[procedure]] (= z1 z2 z3 ...) +;; [[procedure]] (< x1 x2 x3 ...) +;; [[procedure]] (<= x1 x2 x3 ...) + +(define (* x . args) + (cond ((null? args) + x) + ((null? (cdr args)) + (%* x (car args))) + (else + (let loop ((value x) + (rest args)) + (if (null? rest) + value + (loop (%* value (car rest)) + (cdr rest))))))) + +(define (+ x . args) + (cond ((null? args) + x) + ((null? (cdr args)) + (%+ x (car args))) + (else + (let loop ((value x) + (rest args)) + (if (null? rest) + value + (loop (%+ value (car rest)) + (cdr rest))))))) + +(define (- x . args) + (cond ((null? args) + (%- 0 x)) + ((null? (cdr args)) + (%- x (car args))) + (else + (let loop ((value x) + (rest args)) + (if (null? rest) + value + (loop (%- value (car rest)) + (cdr rest))))))) + +(define (= x y . rest) + (if (null? rest) + (%= x y) + (and (%= x y) + (let loop ((args rest)) + (if (null? args) + #t + (and (%= x (car args)) + (loop (cdr args)))))))) + +(define (< x y . args) + (cond ((null? args) + (%< x y)) + (else + (and (%< x y) + (let loop ((current y) + (rest args)) + (cond ((null? rest) + #t) + (else + (and (%< current (car rest)) + (loop (car rest) + (cdr rest)))))))))) + +(define (<= x y . args) + (cond ((null? args) + (%<= x y)) + (else + (and (%<= x y) + (let loop ((current y) + (rest args)) + (cond ((null? rest) + #t) + (else + (and (%<= current (car rest)) + (loop (car rest) + (cdr rest)))))))))) + +;; partial implementations of >, >= + +(define (> x y . args) + (cond ((null? args) + (not (%<= x y))) + (else + (and (not (%<= x y)) + (let loop ((current y) + (rest args)) + (cond ((null? rest) + #t) + (else + (and (not (%<= current (car rest))) + (loop (car rest) + (cdr rest)))))))))) + +(define (>= x y . args) + (cond ((null? args) + (not (%< x y))) + (else + (and (not (%< x y)) + (let loop ((current y) + (rest args)) + (cond ((null? rest) + #t) + (else + (and (not (%< current (car rest))) + (loop (car rest) + (cdr rest)))))))))) + +(define (integer? x) + ;; TODO: number tower + (number? x)) + +;; Stub implementations of the functions below are provided assuming +;; the lack of a number tower. Only integer numbers are supported in +;; these stub implementations. + +;; [[procedure]] (ceiling x) +;; [[procedure]] (complex? obj) +;; [[procedure]] (denominator q) +;; [[procedure]] (exact->inexact z) +;; [[procedure]] (exact? z) +;; [[procedure]] (floor x) +;; [[procedure]] (imag-part z) +;; [[procedure]] (inexact->exact z) +;; [[procedure]] (inexact? z) +;; [[procedure]] (integer? obj) +;; [[procedure]] (magnitude z) +;; [[procedure]] (angle z) +;; [[procedure]] (number->string z radix) +;; [[procedure]] (number->string z) +;; [[procedure]] (numerator q) +;; [[procedure]] (rational? obj) +;; [[procedure]] (real-part z) +;; [[procedure]] (real? obj) +;; [[procedure]] (round x) +;; [[procedure]] (truncate x) + +(define (exact? x) + (if (number? x) + #t + (error "exact?: expects number"))) + +(define (inexact? x) + (if (number? x) + #f + (error "inexact?: expects number"))) + +(define (exact->inexact x) + (if (number? x) + x + (error "exact->inexact: expects number" x))) + +(define (inexact->exact x) + (if (number? x) + x + (error "inexact->exact: expects number" x))) + +(define (truncate x) + (if (number? x) + x + (error "truncate: expects number" x))) + +(define (round x) + (if (number? x) + x + (error "round: expects number" x))) + +(define (floor x) + (if (number? x) + x + (error "floor: expects number" x))) + +(define (ceiling x) + (if (number? x) + x + (error "ceiling: expects number" x))) + +(define (rational? x) + (number? x)) + +(define (numerator x) + (if (number? x) + x + (error "numerator: expects number" x))) + +(define (denominator x) + (if (number? x) + 1 + (error "denominator: expects number" x))) + +(define (real? x) + (number? x)) + +(define (complex? x) + (number? x)) + +(define (magnitude x) + (if (number? x) + x + (error "magnitude: expects number" x))) + +(define (angle x) + (if (number? x) + 0 + (error "angle: expects number" x))) + +(define (real-part x) + (if (number? x) + x + (error "real-part: expects number" x))) + +(define (imag-part x) + (if (number? x) + 0 + (error "imag-part: expects number" x))) + +;; [[procedure]] (acos z) +;; [[procedure]] (asin z) +;; [[procedure]] (atan y x) +;; [[procedure]] (atan z) +;; [[procedure]] (cos z) +;; [[procedure]] (exp z) +;; [[procedure]] (expt z1 z2) +;; [[procedure]] (log z) +;; [[procedure]] (make-polar x3 x) +;; [[procedure]] (make-rectangular x1 x2) +;; [[procedure]] (modulo n1 n2) +;; [[procedure]] (quotient n1 n2) +;; [[procedure]] (remainder n1 n2) +;; [[procedure]] (sin z) +;; [[procedure]] (sqrt z) +;; [[procedure]] (tan z) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; [[procedure]] (close-input-port port) +;; [[procedure]] (close-output-port port) +;; [[procedure]] (char-ready? port) +;; [[procedure]] (char-ready?) +;; [[procedure]] (current-input-port) +;; [[procedure]] (current-output-port) +;; [[procedure]] (eof-object? obj) +;; [[procedure]] (open-input-file filename) +;; [[procedure]] (open-output-file filename) +;; [[procedure]] (peek-char port) +;; [[procedure]] (peek-char) +;; [[procedure]] (read-char port) +;; [[procedure]] (read-char) +;; [[procedure]] (write-char char port) +;; [[procedure]] (write-char char) + +;; stub implementation for now + +(define (char-ready? . args) + (if (null? args) + #t + (if (input-port? (car args)) + #t + (error "char-ready?: expects an input-port" (car args))))) + +(define (peek-char . args) + (if (null? args) + (%peek-char (current-input-port)) + (if (and (input-port? (car args)) + (null? (cdr args))) + (%peek-char (car args)) + (error "peek-char: invalid arguments" args)))) + +(define (read-char . args) + (if (null? args) + (%read-char (current-input-port)) + (if (and (input-port? (car args)) + (null? (cdr args))) + (%read-char (car args)) + (error "read-char: invalid arguments" args)))) + +(define (write-char char . args) + (if (null? args) + (%write-char char (current-output-port)) + (%write-char char (car args)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; OTHER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (error . args) + (display "ERROR") + (for-each (lambda (x) + (display " ") + (display x)) + args) + (newline) + (car 0)) diff --git a/src/rtl/rtlheap.sasm b/src/rtl/rtlheap.sasm new file mode 100644 index 0000000..8312603 --- /dev/null +++ b/src/rtl/rtlheap.sasm @@ -0,0 +1,162 @@ +;; rtlheap.sasm +;; Heap stub routines to interface to the compiler system + +(export rtl-malloc) +(export cp-rtl-base-malloc) +(export cp-rtl-array-malloc) +(export cp-rtl-array-length) +(export rtl-array-length) + +(extern mm-malloc) +(extern mm-fixed-malloc) +(extern gc-invoke) +;; These symbols are defined by either interp-rtlheap or c-rtlheap. +(extern cp-rtl-malloc-failed) +(extern cp-rtl-malloc) + +;; This represents the base (lowest address) of the user code's stack, +;; so the garbage collector will start here when marking pointers in the +;; stack. This is set on entry to the memory management code so that +;; the stack usage of the memory-management code itself does not cause +;; artificial root pointers to be created. +(export gc-root-stack-base) +(global gc-root-stack-base (const 0)) + +;; callee-pop wrapper for mm-malloc +(function (name rtl-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 0)) + (perform (op call) (const cp-rtl-malloc)) + + (perform (op pop-frame)) + (return))) + +;; callee-pop wrapper for cp-rtl-array-length +(function (name rtl-array-length) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 0)) + (perform (op call) (const cp-rtl-array-length)) + + (perform (op pop-frame)) + (return))) + +(function (name cp-rtl-base-malloc) + (locals 0) + (body (assign (reg operand) (sys stack-pointer)) + (assign (reg accum) (const gc-root-stack-base)) + (perform (op store-array) (reg accum) (const 0) (reg operand)) + ;; This represents the entry into the memory management module. + ;; The stack memory above the current stack pointer is entirely in the + ;; user's control, and the stack that will be built below this + ;; point is only relevant to GC and heap management. Therefore + ;; we will set the stack base to this location, so that GC will + ;; only mark roots in the user code's space. + ;; + ;; NOTE This is done before the frame is pushed for a good reason! + ;; Otherwise the stack base would include the locals of this function. + + (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; Check to see if the requested allocation will fit in the + ;; fixed-size heap + (assign (temp test) (op less-than-or-equal) (arg 0) (const 16)) + (branch-zero (label cp-rtl-base-malloc/bigalloc) (temp test)) + + ;; It will; attempt to allocate from the fixed-size heap + (push (arg 0)) + (perform (op call) (const mm-fixed-malloc)) + (assign (temp pointer) (reg accum)) + (branch-nonzero (label cp-rtl-base-malloc/nogc) (temp pointer)) + + ;; It fits in the fixed-size heap, but that heap is full. + ;; Let's try to GC it before we move on to the var-heap. + (perform (op call) (const gc-invoke)) + (push (arg 0)) + (perform (op call) (const mm-fixed-malloc)) + (assign (temp pointer) (reg accum)) + (branch-nonzero (label cp-rtl-base-malloc/nogc) (temp pointer)) + + ;; The small heap is full. Try the big heap before + ;; we bail out. We'll just fall right through to + ;; the 'bigalloc' label. + + (label cp-rtl-base-malloc/bigalloc) + + ;; Well, the small heap didn't work out. Attempt to + ;; alloc from the variable-sized heap. + + (push (arg 0)) + (perform (op call) (const mm-malloc)) + (assign (temp pointer) (reg accum)) + + ;; If malloc succeeded, just return the result. + + (branch-nonzero (label cp-rtl-base-malloc/nogc) (temp pointer)) + + ;; Malloc didn't succeed; let's GC the heap and try + ;; again. + + (perform (op call) (const gc-invoke)) + (push (arg 0)) + (perform (op call) (const mm-malloc)) + (assign (temp pointer) (reg accum)) + (branch-nonzero (label cp-rtl-base-malloc/nogc) (temp pointer)) + + ;; Even after the GC, we still failed. Nothing + ;; to do except bail out or expand the heap. + + (push (arg 0)) + (perform (op call) (const cp-rtl-malloc-failed)) + + ;; This should be unreachable. We do not expect + ;; the cp-rtl-malloc-failed function to return. + + (label cp-rtl-base-malloc/nogc) + + ;; Done! We got a pointer from malloc. Loop + ;; through the buffer and zero it out. + + (assign (temp index) (const 0)) + (label cp-rtl-base-malloc/beginzero) + (assign (temp test) (op less-than) (temp index) (arg 0)) + (branch-zero (label cp-rtl-base-malloc/endzero) (temp test)) + (perform (op store-array) (temp pointer) (temp index) (const 0)) + (assign (temp index) (op add) (temp index) (const 1)) + (goto (label cp-rtl-base-malloc/beginzero)) + + (label cp-rtl-base-malloc/endzero) + (assign (reg accum) (temp pointer)) + (perform (op pop-frame)) + (return (const 1)))) + +(function (name cp-rtl-array-malloc) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (temp push-value) (op add) (arg 0) (const 2)) + (push (temp push-value)) + (perform (op call) (const cp-rtl-malloc)) + (perform (op store-array) (reg accum) (const 0) (arg 0)) + (perform (op store-array) (reg accum) (const 1) (const #x80000000)) + (assign (reg accum) (op add-pointer) (reg accum) (const 2)) + + (perform (op pop-frame)) + (return (const 1)))) + +(function (name cp-rtl-array-length) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg accum) (op load-array) (arg 0) (const -2)) + + (perform (op pop-frame)) + (return (const 1)))) diff --git a/src/rtl/rtlscheme.c b/src/rtl/rtlscheme.c new file mode 100644 index 0000000..ffdbb80 --- /dev/null +++ b/src/rtl/rtlscheme.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +int SYM(c_scheme_argc) = 0; +int **SYM(c_scheme_argv) = NULL; + +extern void *SYM(c_scheme_rtl_init_argv)(); + +void rtlscheme_init_argv(int argc, char **argv) { + int i, j, n; + int *str; + + SYM(c_scheme_argc) = argc; + SYM(c_scheme_argv) = (int**)malloc(sizeof(int*) * (argc + 2)); + SYM(c_scheme_argv)[0] = (int*)argc; + SYM(c_scheme_argv)[1] = (int*)(5 | 0x80000000); + for (i = 0; i < argc; ++i) { + n = strlen(argv[i]); + str = (int*)malloc(sizeof(int) * (n+3)); + SYM(c_scheme_argv)[i+2] = str; + str[0] = n; + str[1] = 6; + for (j = 0; j < n; ++j) { + str[j+2] = argv[i][j]; + } + str[n+2] = 0; + } + + SYM(c_scheme_rtl_init_argv)(); +} + +FILE* SYM(c_scheme_get_stdin)(void) { + return stdin; +} + +FILE* SYM(c_scheme_get_stdout)(void) { + return stdout; +} + +void SYM(c_scheme_type_error)(int expected_type, void *obj) { + _ftprintf(stderr, TEXT("scheme type error: expected:%d %p\n"), expected_type, obj); + _ftprintf(stderr, TEXT(" actual:%d\n"), (obj ? ((int*)obj)[1] : 0)); + ExitProcess(1); +} /* c_scheme_type_error */ + +void SYM(c_scheme_arg_count_error)(int actual_args, int expected_args) { + _ftprintf(stderr, TEXT("scheme arg count error; expected: %d actual: %d"), expected_args, actual_args); + ExitProcess(1); +} /* c_scheme_arg_count_error */ + +void SYM(c_scheme_bounds_error)(int index, int length, int type) { + _ftprintf(stderr, TEXT("scheme bounds check error; index: %d bound: %d type: %d"), index, length, type); + ExitProcess(1); +} + +int SYM(c_scheme_open_file)(const int *wide_fname, int len, int read) { + TCHAR fname[1024], *iter; + int i; + + if (len >= 1024) { + _ftprintf(stderr, TEXT("file name is too long (%d)"), len); + ExitProcess(1); + } + + for (iter = fname, i = 0; i < len; ++i, ++iter, ++wide_fname) + *iter = (TCHAR)*wide_fname; + *iter = TEXT('\0'); + i = (int)_tfopen(fname, read ? TEXT("r") : TEXT("w")); + return i; +} /* c_scheme_open_file */ + +int SYM(c_scheme_close_file)(FILE* file) { + return fclose(file); +} /* c_scheme_close_file */ + +int SYM(c_scheme_read_file)(int file) { + return _fgettc((FILE*)file); +} /* c_scheme_read_file */ + +int SYM(c_scheme_write_file)(int c, int file) { + return _fputtc(c, (FILE*)file); +} /* c_scheme_write_file */ + +const char* SYM(c_scheme_getenv)(const int *wide_name, int len) { + TCHAR name[1024], *iter; + int i; + const char *env; + + if (len >= 1024) { + _ftprintf(stderr, TEXT("file name is too long (%d)"), len); + ExitProcess(1); + } + + for (iter = name, i = 0; i < len; ++i, ++iter, ++wide_name) + *iter = (TCHAR)*wide_name; + *iter = TEXT('\0'); + /*_ftprintf(stderr, TEXT("getenv (%d) [%s]=%s\n"), len, name, getenv(name));*/ + return getenv(name); +} /* c_scheme_getenv */ + +int SYM(c_scheme_delete_file)(const int *wide_fname, int len) { + TCHAR fname[1024], *iter; + int i; + + if (len >= 1024) { + _ftprintf(stderr, TEXT("file name is too long (%d)"), len); + ExitProcess(1); + } + + for (iter = fname, i = 0; i < len; ++i, ++iter, ++wide_fname) + *iter = (TCHAR)*wide_fname; + *iter = TEXT('\0'); + i = (int)unlink(fname); + return i; +} /* c_scheme_delete_file */ + +int SYM(c_scheme_rename_file)(const int *wide_fname, int len, const int *wide_fname2, int len2) { + TCHAR fname[1024], fname2[1024], *iter; + int i; + + if (len >= 1024) { + _ftprintf(stderr, TEXT("file name is too long (%d)"), len); + ExitProcess(1); + } + + for (iter = fname, i = 0; i < len; ++i, ++iter, ++wide_fname) + *iter = (TCHAR)*wide_fname; + *iter = TEXT('\0'); + + for (iter = fname2, i = 0; i < len2; ++i, ++iter, ++wide_fname2) + *iter = (TCHAR)*wide_fname2; + *iter = TEXT('\0'); + + i = (int)rename(fname, fname2); + return i; +} /* c_scheme_rename_file */ + +int SYM(c_scheme_stat_file)(const int *wide_fname, int len, int **vec, int vec_len) { + TCHAR fname[1024], *iter; + struct stat buf; + int i; + + if (vec_len != 10) { + _ftprintf(stderr, TEXT("c_scheme_stat_file vec_len must be 10 (%d)"), vec_len); + ExitProcess(1); + } + + if (len >= 1024) { + _ftprintf(stderr, TEXT("file name is too long (%d)"), len); + ExitProcess(1); + } + + for (iter = fname, i = 0; i < len; ++i, ++iter, ++wide_fname) + *iter = (TCHAR)*wide_fname; + *iter = TEXT('\0'); + + i = stat(fname, &buf); + if (i == 0) { + vec[7][0] = buf.st_size; + vec[9][0] = buf.st_mtime; + } + + return i; +} /* c_scheme_stat_file */ + +int SYM(c_scheme_current_seconds)() { + static time_t t_base = 0; + time_t t_now; + if (t_base == 0) { time(&t_base); } + time(&t_now); + return t_now - t_base; +} /* c_scheme_current_seconds */ + +int SYM(c_scheme_current_milliseconds)() { + return (int)GetTickCount(); +} diff --git a/src/rtl/rtlscheme.sasm b/src/rtl/rtlscheme.sasm new file mode 100644 index 0000000..3087426 --- /dev/null +++ b/src/rtl/rtlscheme.sasm @@ -0,0 +1,499 @@ +;; rtlscheme.sasm +;; + +(extern cp-rtl-malloc) +(extern c-scheme-type-error) +(extern c-scheme-arg-count-error) +(extern c-scheme-bounds-error) +(extern c-scheme-open-file) +(extern c-scheme-close-file) +(extern c-scheme-read-file) +(extern c-scheme-write-file) +(extern c-scheme-get-stdin) +(extern c-scheme-get-stdout) +(extern c-scheme-getenv) +(extern c-scheme-delete-file) +(extern c-scheme-rename-file) +(extern c-scheme-stat-file) +(extern c-scheme-current-seconds) +(extern c-scheme-current-milliseconds) +(extern c-scheme-argv) +(extern $scmliteral-unspecified) + +(export scheme-rtl-runtime-type-error) +(export scheme-rtl-runtime-argument-count-error) +(export scheme-rtl-runtime-bounds-error) +(export scheme-rtl-close-file-handle) +(export scheme-rtl-get-stdin-handle) +(export scheme-rtl-get-stdout-handle) +(export scheme-rtl-open-input-file-handle) +(export scheme-rtl-open-output-file-handle) +(export scheme-rtl-read-byte) +(export scheme-rtl-write-byte) +(export scheme-rtl-getenv) +(export scheme-rtl-delete-file) +(export scheme-rtl-rename-file) +(export scheme-rtl-stat-file) +(export scheme-rtl-current-seconds) +(export scheme-rtl-current-milliseconds) +(export scheme-rtl-strlen) +(export scheme-rtl-strcpy) +(export scheme-rtl-mkstring) +(export c-scheme-rtl-init-argv) +(export $scmglobal--Asargv-As) + +(global $scmglobal--Asargv-As + (const 0) + ) + +(function (name c-scheme-rtl-init-argv) + (locals 0) + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (save (reg index)) + (assign (reg accum) (label c-scheme-argv)) + (assign (reg index) (op load-array) (reg accum) (const 0)) + (assign (reg accum) (label $scmglobal--Asargv-As)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + (restore (reg index)) + + (perform (op pop-frame)) + (return))) + +(function (name scheme-rtl-runtime-type-error) + (locals 0) +;; +;; arg0: int - the expected type tag +;; arg1: void* - the actual object +;; return: none +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 1)) + (push (arg 0)) + (perform (op call) (label c-scheme-type-error)) + + (assign (reg accum) (label $scmliteral-unspecified)) + (perform (op pop-frame)) + (return (const 2)))) + +(function (name scheme-rtl-runtime-argument-count-error) + (locals 0) + + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 1)) + (push (arg 0)) + (perform (op call) (label c-scheme-arg-count-error)) + + (assign (reg accum) (label $scmliteral-unspecified)) + (perform (op pop-frame)) + (return (const 2)))) + +(function (name scheme-rtl-runtime-bounds-error) + (locals 0) + + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 2)) + (push (arg 1)) + (push (arg 0)) + (perform (op call) (label c-scheme-bounds-error)) + (pop (const 3)) + + (assign (reg accum) (label $scmliteral-unspecified)) + (perform (op pop-frame)) + (return (const 3)))) + +(function (name scheme-rtl-close-file-handle) + (locals 0) +;; +;; arg0: FILE* - the CRT file handle. +;; return: none +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 0)) + (perform (op call) (label c-scheme-close-file)) + (pop (const 1)) + + (perform (op pop-frame)) + (return (const 1)))) + +(function (name scheme-rtl-get-stdin-handle) + (locals 0) +;; +;; +;; return: FILE* +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op call) (label c-scheme-get-stdin)) + + (perform (op pop-frame)) + (return (const 0)))) + +(function (name scheme-rtl-get-stdout-handle) + (locals 0) +;; +;; +;; return: FILE* +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op call) (label c-scheme-get-stdout)) + + (perform (op pop-frame)) + (return (const 0)))) + +(function (name scheme-rtl-open-input-file-handle) + (locals 0) +;; +;; arg0: schar* - string pointer +;; arg1: int - string length +;; return: FILE* +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; arg 2 - a flag indicating read mode. + (assign (reg accum) (const 1)) + (push (reg accum)) + ;; arg 1 - string length. + (assign (reg accum) (arg 1)) + (push (reg accum)) + ;; arg 0 - string pointer + (assign (reg accum) (arg 0)) + (push (reg accum)) + + (perform (op call) (label c-scheme-open-file)) + (pop (const 3)) + + (perform (op pop-frame) (const 0)) + (return (const 2)))) + +(function (name scheme-rtl-open-output-file-handle) + (locals 0) +;; +;; arg0: schar* - string pointer +;; arg1: int - string length +;; return: FILE* +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + ;; arg 2 - a flag indicating write mode. + (assign (reg accum) (const 0)) + (push (reg accum)) + ;; arg 1 - string length. + (assign (reg accum) (arg 1)) + (push (reg accum)) + ;; arg 0 - string pointer + (assign (reg accum) (arg 0)) + (push (reg accum)) + + (perform (op call) (label c-scheme-open-file)) + (pop (const 3)) + + (perform (op pop-frame) (const 0)) + (return (const 2)))) + +(function (name scheme-rtl-read-byte) + (locals 0) +;; +;; arg0: FILE* +;; return: int +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 0)) + (perform (op call) (const c-scheme-read-file)) + (pop (const 1)) + + (perform (op pop-frame)) + (return (const 1)))) + +(function (name scheme-rtl-write-byte) + (locals 0) +;; +;; arg0: schar +;; arg1: FILE* +;; return: int +;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (push (arg 1)) + (push (arg 0)) + (perform (op call) (const c-scheme-write-file)) + (pop (const 2)) + + (perform (op pop-frame)) + (return (const 2)))) + +(function (name scheme-rtl-getenv) + (locals 0) + ;; + ;; arg0: schar* - string pointer + ;; arg1: int - string length + ;; return: char* - C string pointer + ;; + (body + (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg accum) (arg 1)) + (push (reg accum)) + (assign (reg accum) (arg 0)) + (push (reg accum)) + (perform (op call) (label c-scheme-getenv)) + (pop (const 2)) + + (perform (op pop-frame) (const 0)) + (return (const 2)) + )) + +(function (name scheme-rtl-delete-file) + (locals 0) + ;; + ;; arg0: schar* - string pointer + ;; arg1: int - string length + ;; return: int - status, 0 indicates success + ;; + (body + (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg accum) (arg 1)) + (push (reg accum)) + (assign (reg accum) (arg 0)) + (push (reg accum)) + (perform (op call) (label c-scheme-delete-file)) + (pop (const 1)) + + (perform (op pop-frame) (const 0)) + (return (const 2)) + )) + +(function (name scheme-rtl-rename-file) + (locals 0) + ;; + ;; arg0: schar* - string1 pointer + ;; arg1: int - string1 length + ;; arg2: schar* - string2 pointer + ;; arg3: int - string2 length + ;; return: int - status, 0 indicates success + ;; + (body + (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg accum) (arg 3)) + (push (reg accum)) + (assign (reg accum) (arg 2)) + (push (reg accum)) + (assign (reg accum) (arg 1)) + (push (reg accum)) + (assign (reg accum) (arg 0)) + (push (reg accum)) + (perform (op call) (label c-scheme-rename-file)) + (pop (const 4)) + + (perform (op pop-frame) (const 0)) + (return (const 4)) + )) + +(function (name scheme-rtl-stat-file) + (locals 0) + ;; + ;; arg0: schar* - string pointer + ;; arg1: int - string length + ;; arg2: int* - vector body pointer + ;; arg3: int - vector length + ;; return: int - status, 0 indicates success + ;; + (body + (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg accum) (arg 3)) + (push (reg accum)) + (assign (reg accum) (arg 2)) + (push (reg accum)) + (assign (reg accum) (arg 1)) + (push (reg accum)) + (assign (reg accum) (arg 0)) + (push (reg accum)) + (perform (op call) (label c-scheme-stat-file)) + (pop (const 4)) + + (perform (op pop-frame) (const 0)) + (return (const 1)) + )) + +(function (name scheme-rtl-current-seconds) + (locals 0) + ;; + ;; + ;; return: int + ;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op call) (label c-scheme-current-seconds)) + + (perform (op pop-frame) (const 0)) + (return (const 0)))) + +(function (name scheme-rtl-current-milliseconds) + (locals 0) + ;; + ;; + ;; return: int + ;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (perform (op call) (label c-scheme-current-milliseconds)) + + (perform (op pop-frame) (const 0)) + (return (const 0)))) + +(function (name scheme-rtl-strlen) + (locals 0) + ;; + ;; arg0: char* - string + ;; return: int - length + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg operand) (const 0)) + (assign (reg index) (arg 0)) + + (label scheme-rtl-strlen/loop) + (assign (reg accum) (op load-array) (reg index) (const 0)) + + (assign (reg this) (op bit-and) (reg accum) (const #x000000ff)) + (branch-zero (label scheme-rtl-strlen/done) (reg this)) + + (assign (reg operand) (op add) (reg operand) (const 1)) + (assign (reg this) (op bit-and) (reg accum) (const #x0000ff00)) + (branch-zero (label scheme-rtl-strlen/done) (reg this)) + + (assign (reg operand) (op add) (reg operand) (const 1)) + (assign (reg this) (op bit-and) (reg accum) (const #x00ff0000)) + (branch-zero (label scheme-rtl-strlen/done) (reg this)) + + (assign (reg operand) (op add) (reg operand) (const 1)) + (assign (reg this) (op bit-and) (reg accum) (const #xff000000)) + (branch-zero (label scheme-rtl-strlen/done) (reg this)) + + (assign (reg operand) (op add) (reg operand) (const 1)) + (assign (reg index) (op add-pointer) (reg index) (const 1)) + (goto (label scheme-rtl-strlen/loop)) + + (label scheme-rtl-strlen/done) + (assign (reg accum) (reg operand)) + (perform (op pop-frame) (const 0)) + (return (const 1)))) + +(function (name scheme-rtl-strcpy) + (locals 0) + ;; + ;; arg0: char* - C source string + ;; arg1: int* - scheme destination string + ;; return: void + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg index) (arg 0)) + (assign (reg operand) (arg 1)) + + (label scheme-rtl-strcpy/loop) + ;; copy + (assign (reg accum) (op load-array) (reg index) (const 0)) + + ;; byte 0 - LSB + (assign (reg this) (op bit-and) (reg accum) (const #x000000ff)) + (perform (op store-array) (reg operand) (const 0) (reg this)) + (branch-zero (label scheme-rtl-strcpy/done) (reg this)) + (assign (reg operand) (op add-pointer) (reg operand) (const 1)) + + ;; byte 1 + (assign (reg accum) (op bit-rshift) (reg accum) (const 8)) + (assign (reg this) (op bit-and) (reg accum) (const #x000000ff)) + (perform (op store-array) (reg operand) (const 0) (reg this)) + (branch-zero (label scheme-rtl-strcpy/done) (reg this)) + (assign (reg operand) (op add-pointer) (reg operand) (const 1)) + + ;; byte 2 + (assign (reg accum) (op bit-rshift) (reg accum) (const 8)) + (assign (reg this) (op bit-and) (reg accum) (const #x000000ff)) + (perform (op store-array) (reg operand) (const 0) (reg this)) + (branch-zero (label scheme-rtl-strcpy/done) (reg this)) + (assign (reg operand) (op add-pointer) (reg operand) (const 1)) + + ;; byte 3 + (assign (reg accum) (op bit-rshift) (reg accum) (const 8)) + (assign (reg this) (op bit-and) (reg accum) (const #x000000ff)) + (perform (op store-array) (reg operand) (const 0) (reg this)) + (branch-zero (label scheme-rtl-strcpy/done) (reg this)) + (assign (reg operand) (op add-pointer) (reg operand) (const 1)) + + (assign (reg index) (op add-pointer) (reg index) (const 1)) + (goto (label scheme-rtl-strcpy/loop)) + + (label scheme-rtl-strcpy/done) + (perform (op pop-frame) (const 0)) + (return (const 2)))) + +(function (name scheme-rtl-mkstring) + (locals 0) + ;; + ;; arg0: char* - source string + ;; return: scheme* - string + ;; + (body (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + + (assign (reg accum) (arg 0)) + + ;; get the string length + (push (reg accum)) + (perform (op call) (label scheme-rtl-strlen)) + (save (reg accum)) + ;; add 3, for the GCDW, array length, and NUL terminator + (assign (reg accum) (op add) (reg accum) (const 3)) + (push (reg accum)) + (perform (op call) (label cp-rtl-malloc)) + + ;; index=length + (restore (reg index)) + (perform (op store-array) (reg accum) (const 0) (reg index)) + ;; store the scheme string type tag + (perform (op store-array) (reg accum) (const 1) (const 6)) + + ;; operand = source string + (assign (reg operand) (arg 0)) + ;; index = destination string (no scheme string header) + (assign (reg index) (op add-pointer) (reg accum) (const 2)) + (save (reg accum)) + + ;; call strcpy + (push (reg index)) ; destination + (push (reg operand)) ; source + (perform (op call) (label scheme-rtl-strcpy)) + + (restore (reg accum)) ; allocated string + + (label mkstring/done) + (perform (op pop-frame) (const 0)) + (return (const 1)))) diff --git a/src/rtl/sasm.h b/src/rtl/sasm.h new file mode 100644 index 0000000..e66555c --- /dev/null +++ b/src/rtl/sasm.h @@ -0,0 +1,28 @@ +#ifndef SASM_H_ +#define SASM_H_ + +#ifdef _WIN32 +# include +# include +# define SYM(x) x +#else +# define _tmain main +# define _tprintf printf +# define _ftprintf fprintf +# define _tfopen fopen +# define _fgettc fgetc +# define _fputtc fputc +# define _tcslen strlen +# define TEXT(x) x +# include +# define ExitProcess exit +# define TCHAR char +# define VOID void +# ifdef __CYGWIN__ +# define SYM(x) x +# else +# define SYM(x) _##x +# endif +#endif + +#endif /* SASM_H_ */ diff --git a/src/rtl/scheme-main.sasm b/src/rtl/scheme-main.sasm new file mode 100644 index 0000000..340c329 --- /dev/null +++ b/src/rtl/scheme-main.sasm @@ -0,0 +1,17 @@ +(extern $scheme-entry:rtl/r5rs-wrap) +(extern $scheme-entry:rtl/r5rs-library) +(extern $scheme-entry:scheme-main) +(export $sasm-scheme-main) +(entry $sasm-scheme-main) +(function + (name $sasm-scheme-main) + (locals 0) + (body + (perform (op push-frame)) + (perform (op reserve-locals) (const 0)) + (perform (op call) (const $scheme-entry:rtl/r5rs-wrap)) + (perform (op call) (const $scheme-entry:rtl/r5rs-library)) + (perform (op call) (const $scheme-entry:scheme-main)) + (perform (op pop-frame)) + (return (const 0)) + )) diff --git a/src/rtl/scheme.java b/src/rtl/scheme.java new file mode 100644 index 0000000..9cd116f --- /dev/null +++ b/src/rtl/scheme.java @@ -0,0 +1,1015 @@ +// scheme.java -*-Java-*- +// Runtime library for Scheme, written in MiniJava + +// +// R5RS primitive types: +// +// Numbers <-- int only, no tower b/c no FP yet +// Boolean <-- done +// Characters <-- done +// Strings <-- done +// Symbols <-- done +// Vector <-- done +// Input-Port <-- need interop +// Output-Port <-- need interop +// Nil <-- done +// End-of-File <-- done +// Procedure <-- done +// Pair <-- done +// +// Improper Lambda <-- invoke by array should make this easy +// Continuations <-- CPS before AST transform +// + + +class scheme +{ + public static void main( String[] args ) { { } } +} +class String +{ + char[] chars; + + public String(char[] c) { + chars = c; + } + + public char[] toCharArray() { + return chars; + } +} + + +class object +{ + __sasm_impl public static object[] init_frame( object[] args, object[] frame ) = sasm_scheme_init_frame; + __sasm_impl public static object[] get_frame( object[] frame, int up ) = sasm_scheme_get_frame; + __sasm_impl public static int sasm_scheme_type_error(char[] str, int len) = sasm_scheme_type_error; + public static int scheme_type_error(String s) { + int i; + i = object.sasm_scheme_type_error(s.toCharArray(), + s.toCharArray().length); + } + public static int int_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return i; + } + + public static boolean bool_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return false; + } + public static object obj_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return new object(); + } + public static object[] objarr_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return new object[1]; + } + public static char char_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return '\0'; + } + public static char[] chararr_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return new char[1]; + } + public static object[] varargs_type_error(String s) + { return object.objarr_type_error(s); } + + + /* args is the frame that was allocated for the call. */ + /* req is the number of arguments that the varargs function requires + + 1. e.g. for (lambda (a b . c) ) req is 3. */ + public static object[] init_varargs( object[] args, int req ) { + int i; + object list; + object[] outargs; + + if (args.length < req) { + outargs = object.varargs_type_error("provided too few args to varargs function\n"); + } else { + if (args.length == req) { + outargs = new object[req+1]; + } else { + outargs = args; + } /* if */ + } /* if */ + i = args.length - 1; + list = new scheme_nil(); + while (!(i < req)) { + list = new scheme_pair( args[i], list ); + i = i - 1; + } /* while */ + if (outargs == args) { + /* nothing. */ + } else { + i = 0; + while (i < req) { + outargs[i] = args[i]; + i = i + 1; + } /* while */ + } /* if */ + outargs[req] = list; + return outargs; + } /* init_varargs */ + + public static boolean is_list(object head) { + /* The basic algorithm of this function is to walk through the + list with two iterators simultaneously. The fast iterator + skips ahead two pairs at each iteration. The slow iterator + skips ahead one pair at each iteration. This way, if there is + a cycle, the slow and fast will eventually match. We can + detect the cycle without additional O(N) memory (where N is the + number of elements in the pair structure). */ + /* If at any time you reach nil (end-of-list) or a non-pair + object, the iteration also completes with a result. */ + boolean result; + boolean done; + object slow; + object fast; + object next; + + /* First we must check to see that the list is at least two + elements; otherwise we can answer trivially, and we do not have + sufficient primer to begin the algorithm. */ + if (head.is_nil()) { + /* The head element is nil, so we have a trivial answer. */ + result = true; + } else { + if (!head.is_pair()) { + /* The head element is not a pair, so we have a trivial + answer. */ + result = false; + } else { + /* We have enough information to begin the iteration, since we + can initialize the slow iterator to the head and the fast + iterator to one past the head. */ + done = false; + result = false; + slow = head; + fast = head.pair_cdr(); + while (!done) { + /* We set done to true here pre-emptively; most blocks below + result in done being set to true, and only one results in + it being set to false. However, we might want to change + this because at run- time most iterations through the + loop will have to assign done, whereas in the opposite + manner only one iteration through the loop would have to + assign done. */ + done = true; + if (fast == slow) { + /* We have detected a cycle. */ + result = false; + } else { + if (slow.is_pair()) { + /* 'slow' is a pair so we aren't done yet. Go on and + check 'fast' to see its status. */ + if (fast.is_pair()) { + /* 'slow' and 'fast' are both pairs. We must look to + see if it is possible to advance the fast iterator + forward two pairs. If not, we have our answer + trivially. */ + next = fast.pair_cdr(); + if (next == slow) { + /* We have detected a cycle pre-emptively. Might as + well bail here instead of doing more work. */ + result = false; + } else { + if (next.is_pair()) { + /* We need to iterate and check the next pair. */ + /* This is the one code path through the iteration + where we do not terminate. */ + done = false; + slow = slow.pair_cdr(); + fast = next.pair_cdr(); + } else { + /* 'next' is not a pair. It is either nil, + signifying the end of a list, or this is not a + list. */ + result = next.is_nil(); + } /* if */ + } /* if */ + } else { + /* 'fast' is not a pair. It is either nil, + signifying the end of a list, or this is not a + list. */ + result = fast.is_nil(); + } /* if */ + } else { + /* 'slow' is not a pair. It is either nil, + signifying the end of a list, or this is not a + list. */ + result = slow.is_nil(); + } /* if */ + } /* if */ + } /* while */ + } /* if */ + } /* if */ + return result; + } /* is_list */ + + public static object[] convert_apply_args_to_array2(object[] fixed, object head) { + int len; + int i; + object curr; + object[] result; + + if (!object.is_list(head)) { + result = object.objarr_type_error("'apply' requires a proper list\n"); + } else { + /* Compute the length of the list, adding it to the length of + the fixed array. */ + len = fixed.length; + curr = head; + while (!curr.is_nil()) { + len = len + 1; + curr = curr.pair_cdr(); + } /* while */ + /* Allocate the new array. */ + result = new object[len]; + /* Assign the elements of the fixed array to the result + array. */ + i = 0; + while (i < fixed.length) { + result[i] = fixed[i]; + i = i + 1; + } /* while */ + /* check_assertion(i == fixed.length); */ + /* check_assertion(i <= len); */ + /* check_assertion(i < len || head.is_nil()); */ + /* Assign the elements of the argument list to the result + array. */ + curr = head; + while (i < len) { + result[i] = curr.pair_car(); + i = i + 1; + curr = curr.pair_cdr(); + } /* while */ + } /* if */ + return result; + } /* convert_apply_args_to_array2 */ + + public static object[] convert_apply_args_to_array(object head) { + /* 'head' is the list of parameters to Scheme function 'apply'. + This means that the list was built by the runtime library and + is "safe", i.e. we can skip the is_list check. It also means + that the last element of 'head' is itself an embedded list + (this follows directly from the form of the apply argument list + from r5rs). */ + /* Walk through 'head' and its embedded list, and flatten this out + into a new argument array, which is the return value of the + routine. */ + int len; + int outer_length; + int i; + object curr; + object[] result; + object last; + + /* It is assumed that 'head' is a correct list, since it was built + by the runtime. We avoid the is_list check here for + efficiency. */ + if (/*!object.is_list(head)*/ false) { + result = object.objarr_type_error("'apply' requires a proper list\n"); + } else { + /* Compute the length of the list. */ + len = 0; + curr = head; + /* 'last' is initialized to something here to prevent a + warning from javac. We assume that it will be set in the + loop, or else length will be 0 which is an error. */ + last = head; + while (!curr.is_nil()) { + len = len + 1; + last = curr.pair_car(); + curr = curr.pair_cdr(); + } /* while */ + if (len == 0) { + /* The 'apply' function requires at least one argument -- the + embedded list. */ + result = object.objarr_type_error("'apply' requires at least one argument\n"); + } else { + /* Subtract 1 for the embedded list which was counted above. */ + len = len - 1; + outer_length = len; + /* At this point, 'last' points to the embedded list that will + become the tail of the result array. We need to ensure this + is a proper list before working with it. */ + curr = last; + if (!object.is_list(curr)) { + result = object.objarr_type_error("'apply' requires a proper list\n"); + } else { + /* Now walk through the embedded list and add its elements to + the required length. */ + while (!curr.is_nil()) { + len = len + 1; + curr = curr.pair_cdr(); + } /* while */ + /* Allocate the new array. */ + result = new object[len]; + /* Assign the elements of the argument list to the result + array. */ + curr = head; + i = 0; + while (i < outer_length) { + result[i] = curr.pair_car(); + i = i + 1; + curr = curr.pair_cdr(); + } /* while */ + /* Assign the elements of the embedded argument list to the + result array. */ + /* check_assertion(curr.pair_cdr().is_nil()); */ + curr = curr.pair_car(); + while (i < len) { + result[i] = curr.pair_car(); + i = i + 1; + curr = curr.pair_cdr(); + } /* while */ + } /* if */ + } /* if */ + } /* if */ + return result; + } /* convert_apply_args_to_array */ + + public static object apply_function(object function, object args) + { + object[] argv; + + argv = object.convert_apply_args_to_array(args); + return function.apply(argv); + } /* apply_function */ + + public static int list_plus(object head) + { + /* Assuming that 'head' is the start of a proper list of integer-type + objects, return the sum of the objects. */ + int val; + + val = 0; + while (!head.is_nil()) { + val = val + head.pair_car().int_value(); + head = head.pair_cdr(); + } /* while */ + return val; + } /* list_plus */ + + public static int list_mul(object head) + { + /* Assuming that 'head' is the start of a proper list of integer-type + objects, return the product of the objects. */ + int val; + + val = 1; + while (!head.is_nil()) { + val = val * head.pair_car().int_value(); + head = head.pair_cdr(); + } /* while */ + return val; + } /* list_mul */ + + public static int list_sub(object x, object head) + { + int val; + + if (head.is_nil()) { + val = 0-x.int_value(); + } else { + val = x.int_value(); + while (!head.is_nil()) { + val = val - head.pair_car().int_value(); + head = head.pair_cdr(); + } /* while */ + } /* if */ + return val; + } /* list_sub */ + + public static boolean list_eq(object x, object y, object head) + { + int last; + int curr; + boolean result; + + last = y.int_value(); + result = x.int_value() == last; + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (last == curr); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_eq */ + + public static boolean list_lt(object x, object y, object head) + { + int last; + int curr; + boolean result; + + last = y.int_value(); + result = x.int_value() < last; + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (last < curr); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_lt */ + + public static boolean list_lteq(object x, object y, object head) + { + int last; + int curr; + int ix; + boolean result; + + last = y.int_value(); + ix = x.int_value(); + result = (!(!(ix < last) && !(ix == last))); + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (!(!(last < curr) && !(last == curr))); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_lteq */ + + public static boolean list_gt(object x, object y, object head) + { + int last; + int curr; + int ix; + boolean result; + + last = y.int_value(); + ix = x.int_value(); + result = (!(ix < last) && !(ix == last)); + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (!(last < curr) && !(last == curr)); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_gt */ + + public static boolean list_gteq(object x, object y, object head) + { + int last; + int curr; + boolean result; + + last = y.int_value(); + result = !(x.int_value() < last); + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (!(last < curr)); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_gteq */ + + public static int string_to_number(char[] str, int radix) { + int val; + int idx; + int digit; + int c; + int stop; + int power; + boolean negative; + + if (0-1 < radix && radix < 17 && 0 < str.length) { + val = 0; + power = 1; + idx = str.length - 1; + if (str[0] == '-') { + negative = true; + stop = 1; + } else { + negative = false; + stop = 0; + } /* if */ + while (!(idx < stop)) { + c = str[idx]; + if ('/' < c && c < ':') { + digit = c - '0'; + } else { + if ('@' < c && c < 'G') { + digit = c - 'A'; + } else { + if ('`' < c && c < 'g') { + digit = c - 'a'; + } else { + digit = radix; + } /* if */ + } /* if */ + } /* if */ + if (digit < radix) { + val = val + (digit * power); + power = power * radix; + } else { + val = object.int_type_error("in string->number, digit out-of-range\n"); + idx = 0-1; + } /* if */ + idx = idx - 1; + } /* while */ + if (negative) { + val = 0-val; + } else { + } /* if */ + } else { + val = object.int_type_error("in string->number, invalid parameter\n"); + } /* if */ + return val; + } /* string_to_number */ + + public static char[] number_to_string(int val, int radix) { + String digits_string; + char[] digits; + char[] result; + int digits_count; + int iter; + int quotient; + int remainder; + int idx; + boolean negative; + + digits_count = 0; + digits_string = "0123456789abcdef"; + digits = digits_string.toCharArray(); + if (val < 0) { + negative = true; + val = 0-val; + } else { + negative = false; + } /* if */ + if (val == 0) { + result = new char[1]; + result[0] = '0'; + } else { + if (negative) { + digits_count = 1; + } else { + digits_count = 0; + } /* if */ + iter = val; + while (!(iter == 0)) { + quotient = 1; + while (quotient * radix < iter) { quotient = quotient + 1; } + if (iter < quotient * radix) { + quotient = quotient - 1; + } else { + } /* if */ + iter = quotient; + digits_count = digits_count + 1; + } /* while */ + result = new char[digits_count]; + if (negative) { + result[0] = '-'; + } else { + } /* if */ + iter = val; + idx = result.length - 1; + while (!(iter == 0)) { + quotient = 1; + while (quotient * radix < iter) { quotient = quotient + 1; } + if (iter < quotient * radix) { + quotient = quotient - 1; + } else { + } /* if */ + remainder = iter - quotient * radix; + iter = quotient; + result[idx] = digits[remainder]; + idx = idx - 1; + } /* while */ + } /* if */ + return result; + } /* number_to_string */ + + // common ////////////////////////////////////////////////////////// + public boolean eq( object o ) { return this == o; } + public boolean eqv( object o ) { return this.eq( o ); } + public boolean equal( object o ) { return this.eqv( o ); } + + // procedure /////////////////////////////////////////////////////// + public boolean is_proc() { return false; } + public object apply( object[] args ) { return object.obj_type_error("attempt to invoke a non-procedure\n"); } + + // bool //////////////////////////////////////////////////////////// + public boolean is_bool() { return false; } + public boolean bool_value() { return object.bool_type_error("expected a boolean\n"); } + + // int ///////////////////////////////////////////////////////////// + public boolean is_int() { return false; } + public int int_value() { return object.int_type_error("expected an int\n"); } + + // char //////////////////////////////////////////////////////////// + public boolean is_char() { return false; } + public char char_value() { return object.char_type_error("expected a character\n"); } + public boolean char_eq( char c ) { return object.bool_type_error("in char=?, expected a character\n"); } + public boolean char_lt( char c ) { return object.bool_type_error("in char?, expected a character\n"); } + public boolean char_lte( char c ) { return object.bool_type_error("in char<=?, expected a character\n"); } + public boolean char_gte( char c ) { return object.bool_type_error("in char>=?, expected a character\n"); } + public int char_value_as_int() { return object.int_type_error("in char->integer, expected a character\n"); } + + // string ////////////////////////////////////////////////////////// + public boolean is_string() { return false; } + public char[] string_value() { return object.chararr_type_error("expected a string\n"); } + public int string_length() { return object.int_type_error("in string-length, expected a string\n"); } + public char string_ref(int i) { return object.char_type_error("in string-ref, expected a string\n"); } + public object string_set(int i, char c) { return object.obj_type_error("in string-set, expected a string\n"); } + + // symbol ////////////////////////////////////////////////////////// + public boolean is_symbol() { return false; } + public char[] symbol_value() { return object.chararr_type_error("expected a symbol\n"); } + + // vector ////////////////////////////////////////////////////////// + public boolean is_vector() { return false; } + public object[] vector_value() { return object.objarr_type_error("expected a vector\n"); } + public int vector_length() { return object.int_type_error("in vector-length, expected a vector\n"); } + public object vector_ref(int i) { return object.obj_type_error("in vector-ref, expected a vector\n"); } + public object vector_set(int i, object o) { return object.obj_type_error("in vector-set!, expected a vector\n"); } + + // end-of-file ///////////////////////////////////////////////////// + public boolean is_eof() { return false; } + + // nil ///////////////////////////////////////////////////////////// + public boolean is_nil() { return false; } + + // pair //////////////////////////////////////////////////////////// + public boolean is_pair() { return false; } + public object pair_car() { return object.obj_type_error("in car, expected a pair\n"); } + public object pair_cdr() { return object.obj_type_error("in cdr, expected a pair\n"); } + public object pair_set_car( object a ) { return object.obj_type_error("in set-car!, expected a pair\n"); } + public object pair_set_cdr( object a ) { return object.obj_type_error("in set-cdr!, expected a pair\n"); } + + // input-port ////////////////////////////////////////////////////// + public boolean is_input_port() { return false; } + public object read_char() { return object.obj_type_error("in read-char, expected an input-port\n"); } + public object peek_char() { return object.obj_type_error("in peek-char, expected an input-port\n"); } + public boolean char_ready() { return object.bool_type_error("in char-ready?, expected an input-port\n"); } + public object close_input_port() { return object.obj_type_error("in close-input-port, expected an input-port\n"); } + + // output-port ///////////////////////////////////////////////////// + public boolean is_output_port() { return false; } + public object write_char( char c ) { return object.obj_type_error("in write-char, expected an output-port\n"); } + public object close_output_port() { return object.obj_type_error("in close-output-port, expected an output-port\n"); } +} + +class scheme_proc extends object +{ + public boolean is_proc() { return true; } +} + +class scheme_bool extends object +{ + boolean bvalue; + + public scheme_bool() { + bvalue = false; + } + + public scheme_bool(boolean b) { + bvalue = b; + } + + public boolean is_bool() { return true; } + public object bool_const( boolean b ) { bvalue = b; return this; } + public boolean bool_value() { return bvalue; } + public boolean eq(object o) { + boolean value; + if (o.is_bool()) { + value = (o.bool_value() == this.bool_value()); + } else { + value = false; + } + return value; + } +} + +class scheme_int extends object +{ + int ivalue; + + public scheme_int() { + ivalue = 0; + } + + public scheme_int( int i ) { + ivalue = i; + } + + public boolean is_int() { return true; } + public object int_const( int i ) { ivalue = i; return this; } + public int int_value() { return ivalue; } +} + +class scheme_char extends object +{ + char cvalue; + + public scheme_char() { + cvalue = '\0'; + } + + public scheme_char( char c ) { + cvalue = c; + } + + public scheme_char( int i ) { + cvalue = scheme_io_interface.make_char(i); + } + + public object char_const(char c) { cvalue = c; return this; } + + public boolean is_char() { return true; } + public char char_value() { return cvalue; } + public boolean char_eq( char c ) { return cvalue == c; } + public boolean char_lt( char c ) { return cvalue < c; } + public boolean char_gt( char c ) { + boolean value; + + if (cvalue < c) { + value = false; + } else { + if (cvalue == c) { + value = false; + } else { + value = true; + } + } + return value; + } + public boolean char_lte( char c ) { + boolean value; + + if (cvalue < c) { + value = true; + } else { + if (cvalue == c) { + value = true; + } else { + value = false; + } + } + return value; + } + public boolean char_gte( char c ) { return !(cvalue < c); } + public int char_value_as_int() { return 0 + cvalue; } +} + +class scheme_string extends object +{ + char[] svalue; + + public scheme_string() { + svalue = new char[0]; + } + + public scheme_string( char[] s ) { + svalue = s; + } + + public scheme_string( int k, char c ) { + int i; + + svalue = new char[k]; + i = 0; + while (i < k) { + svalue[i] = c; + i = i + 1; + } + } + + public boolean is_string() { return true; } + public char[] string_value() { + return svalue; + } + public int string_length() { + return svalue.length; + } + public char string_ref(int i) { + return svalue[i]; + } +} + +class scheme_symbol extends object +{ + char[] svalue; + + public scheme_symbol() { + svalue = new char[0]; + } + + public scheme_symbol( char[] s ) { + svalue = s; + } + + public boolean is_symbol() { return true; } + public char[] symbol_value() { return svalue; } +} + +class scheme_eof extends object +{ + public boolean is_eof() { return true; } +} + +class scheme_nil extends object +{ + public boolean eq(object o) { return o.is_nil(); } + public boolean is_nil() { return true; } +} + +class scheme_vector extends object +{ + object[] value; + + public scheme_vector( int n ) { + value = new object[n]; + } + + public scheme_vector( int n, object o ) { + int i; + value = new object[n]; + i = 0; + while (i < n) { + value[i] = o; + i = i + 1; + } + } + + public boolean is_vector() { return true; } + public object[] vector_value() { return value; } + public int vector_length() { return value.length; } + public object vector_ref(int i) { return value[i]; } + public object vector_set(int i, object o) { value[i] = o; return o; } +} + +class scheme_pair extends object +{ + object car; + object cdr; + + public scheme_pair( object a, object d ) { + car = a; + cdr = d; + } /* scheme_pair */ + + public boolean is_pair() { return true; } + + public object pair_car() { return car; } + public object pair_cdr() { return cdr; } + + public object pair_set_car( object a ) { car = a; return a; } + public object pair_set_cdr( object a ) { cdr = a; return a; } +} + +class scheme_io_interface +{ + __sasm_impl public static int open_file( char[] fname, int len, int read ) + = sasm_scheme_open_file; + __sasm_impl public static int close_file( int file ) + = sasm_scheme_close_file; + __sasm_impl public static int read_file( int file ) + = sasm_scheme_read_file; + __sasm_impl public static int write_file( int file, char c ) + = sasm_scheme_write_file; + __sasm_impl public static char make_char( int ch ) + = sasm_scheme_make_char; + __sasm_impl public static object print_char( char c ) + = sasm_scheme_print_char; + +} + +class scheme_input_port extends object +{ + int f; + scheme_eof eof; + boolean peeked; + object peeked_char; + + public scheme_input_port() { + char[] fname; + + fname = new char[0]; + f = scheme_io_interface.open_file(fname, 0, 1); + eof = new scheme_eof(); + peeked = false; + peeked_char = eof; + } + + public scheme_input_port( char[] fname ) { + f = scheme_io_interface.open_file(fname, fname.length, 1); + eof = new scheme_eof(); + peeked = false; + peeked_char = eof; + } /* scheme_input_port */ + + public boolean is_input_port() { + return true; + } /* is_input_port */ + + public object peek_char() { + object result; + + if (peeked) { + result = peeked_char; + } else { + result = this.read_char(); + peeked_char = result; + peeked = true; + } + return result; + } /* peek_char */ + + public boolean char_ready() { + return true; + } /* char_ready */ + + public object read_char() { + object result; + int c; + + if (f == 0) { + result = eof; + } else { + if (peeked) { + peeked = false; + result = peeked_char; + } else { + c = scheme_io_interface.read_file(f); + if (c < 0) { + result = eof; + } else { + result = new scheme_char( scheme_io_interface.make_char(c) ); + } + } + } + return result; + } /* read_char */ + + public object close_input_port() { + int c; + + if (f == 0) { + /* nothing */ + } else { + c = scheme_io_interface.close_file(f); + f = 0; + } /* if */ + return eof; + } /* close_input_port */ +} /* class scheme_input_port */ + +class scheme_output_port extends object +{ + int f; + + public scheme_output_port() { + char[] fname; + + fname = new char[0]; + f = scheme_io_interface.open_file(fname, 0, 0); + } /* scheme_output_port */ + + public scheme_output_port( char[] fname ) { + f = scheme_io_interface.open_file(fname, fname.length, 0); + } /* scheme_output_port */ + + public boolean is_output_port() { return true; } + + public object write_char( char c ) { + int dontcare; + + if (f == 0) { + /* nothing */ + } else { + dontcare = scheme_io_interface.write_file(f, c); + } /* if */ + return this; + } /* write_char */ + + public object close_output_port() { + int dontcare; + + if (f == 0) { + /* nothing */ + } else { + dontcare = scheme_io_interface.close_file(f); + f = 0; + } /* if */ + return this; + } /* close_output_port */ +} /* class scheme_output_port */ diff --git a/src/rtl/scheme.javap b/src/rtl/scheme.javap new file mode 100644 index 0000000..6ec105f --- /dev/null +++ b/src/rtl/scheme.javap @@ -0,0 +1,1100 @@ +// scheme.java -*-Java-*- +// Runtime library for Scheme, written in MiniJava + +// +// R5RS primitive types: +// +// Numbers <-- int only, no tower b/c no FP yet +// Boolean <-- done +// Characters <-- done +// Strings <-- done +// Symbols <-- done +// Vector <-- done +// Input-Port <-- need interop +// Output-Port <-- need interop +// Nil <-- done +// End-of-File <-- done +// Procedure <-- done +// Pair <-- done +// +// Improper Lambda <-- invoke by array should make this easy +// Continuations <-- CPS before AST transform +// + +#if !TESTING +class scheme +{ + public static void main( String[] args ) { { } } +} +#else /* TESTING */ +class scheme_test +{ + public static void check(String s, int radix, int i) { + int result = object.string_to_number(s.toCharArray(), radix); + if (i != result) { + System.out.println("FAIL: [" + s + "] -> " + result + "; should be: " + i); + } else { + System.out.println("PASS: [" + s + "] -> " + result); + } + } + public static void check(int i, int radix, String s) { + char[] actual = object.number_to_string(i, radix); + boolean equal; + + if (actual.length != s.length()) { + equal = false; + } else { + equal = true; + for (int idx = 0; idx < actual.length; idx++) { + if (s.charAt(idx) != actual[idx]) { + equal = false; + break; + } + } + } + + if (!equal) { + System.out.println("FAIL: " + i + " -> [" + new String(actual) + "]; should be [" + s + "]"); + } else { + System.out.println("PASS: " + i + " -> [" + new String(actual) + "]"); + } + } + public static void main(String[] args) { + check("300", 10, 300); + check(300, 10, "300"); + check("-300", 10, -300); + check(-300, 10, "-300"); + check(-0, 10, "0"); + check("-0", 10, 0); + check("-3", 10, -3); + check("13", 10, 13); + check("10", 2, 2); + check("11", 2, 3); + check(3, 2, "11"); + check(2, 2, "10"); + check("-0000000", 2, 0); + check(120, 10, "120"); + check("120", 10, 120); + } /* main */ +} +#endif /* !TESTING */ + +#if !TESTING +class String +{ + char[] chars; + + public String(char[] c) { + chars = c; + } + + public char[] toCharArray() { + return chars; + } +} +#endif /* !TESTING */ + +class object +{ +#if TESTING + public static int scheme_type_error(String s) { throw new Error(); } + public static int int_type_error(String s) { throw new Error(); } + public static boolean bool_type_error(String s) { throw new Error(); } + public static object obj_type_error(String s) { throw new Error(); } + public static object[] objarr_type_error(String s) { throw new Error(); } + public static char char_type_error(String s) { throw new Error(); } + public static char[] chararr_type_error(String s) { throw new Error(); } + public static object[] varargs_type_error(String s) { throw new Error(); } +#else /* !TESTING */ + __sasm_impl public static object[] init_frame( object[] args, object[] frame ) = sasm_scheme_init_frame; + __sasm_impl public static object[] get_frame( object[] frame, int up ) = sasm_scheme_get_frame; + __sasm_impl public static int sasm_scheme_type_error(char[] str, int len) = sasm_scheme_type_error; + public static int scheme_type_error(String s) { + int i; + i = object.sasm_scheme_type_error(s.toCharArray(), + s.toCharArray().length); + } + public static int int_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return i; + } + + public static boolean bool_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return false; + } + public static object obj_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return new object(); + } + public static object[] objarr_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return new object[1]; + } + public static char char_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return '\0'; + } + public static char[] chararr_type_error(String s) + { int i; + i = object.scheme_type_error(s); + return new char[1]; + } + public static object[] varargs_type_error(String s) + { return object.objarr_type_error(s); } +#endif /* TESTING */ + + /* args is the frame that was allocated for the call. */ + /* req is the number of arguments that the varargs function requires + + 1. e.g. for (lambda (a b . c) ) req is 3. */ + public static object[] init_varargs( object[] args, int req ) { + int i; + object list; + object[] outargs; + + if (args.length < req) { + outargs = object.varargs_type_error("provided too few args to varargs function\n"); + } else { + if (args.length == req) { + outargs = new object[req+1]; + } else { + outargs = args; + } /* if */ + } /* if */ + i = args.length - 1; + list = new scheme_nil(); + while (!(i < req)) { + list = new scheme_pair( args[i], list ); + i = i - 1; + } /* while */ + if (outargs == args) { + /* nothing. */ + } else { + i = 0; + while (i < req) { + outargs[i] = args[i]; + i = i + 1; + } /* while */ + } /* if */ + outargs[req] = list; + return outargs; + } /* init_varargs */ + + public static boolean is_list(object head) { + /* The basic algorithm of this function is to walk through the + list with two iterators simultaneously. The fast iterator + skips ahead two pairs at each iteration. The slow iterator + skips ahead one pair at each iteration. This way, if there is + a cycle, the slow and fast will eventually match. We can + detect the cycle without additional O(N) memory (where N is the + number of elements in the pair structure). */ + /* If at any time you reach nil (end-of-list) or a non-pair + object, the iteration also completes with a result. */ + boolean result; + boolean done; + object slow; + object fast; + object next; + + /* First we must check to see that the list is at least two + elements; otherwise we can answer trivially, and we do not have + sufficient primer to begin the algorithm. */ + if (head.is_nil()) { + /* The head element is nil, so we have a trivial answer. */ + result = true; + } else { + if (!head.is_pair()) { + /* The head element is not a pair, so we have a trivial + answer. */ + result = false; + } else { + /* We have enough information to begin the iteration, since we + can initialize the slow iterator to the head and the fast + iterator to one past the head. */ + done = false; + result = false; + slow = head; + fast = head.pair_cdr(); + while (!done) { + /* We set done to true here pre-emptively; most blocks below + result in done being set to true, and only one results in + it being set to false. However, we might want to change + this because at run- time most iterations through the + loop will have to assign done, whereas in the opposite + manner only one iteration through the loop would have to + assign done. */ + done = true; + if (fast == slow) { + /* We have detected a cycle. */ + result = false; + } else { + if (slow.is_pair()) { + /* 'slow' is a pair so we aren't done yet. Go on and + check 'fast' to see its status. */ + if (fast.is_pair()) { + /* 'slow' and 'fast' are both pairs. We must look to + see if it is possible to advance the fast iterator + forward two pairs. If not, we have our answer + trivially. */ + next = fast.pair_cdr(); + if (next == slow) { + /* We have detected a cycle pre-emptively. Might as + well bail here instead of doing more work. */ + result = false; + } else { + if (next.is_pair()) { + /* We need to iterate and check the next pair. */ + /* This is the one code path through the iteration + where we do not terminate. */ + done = false; + slow = slow.pair_cdr(); + fast = next.pair_cdr(); + } else { + /* 'next' is not a pair. It is either nil, + signifying the end of a list, or this is not a + list. */ + result = next.is_nil(); + } /* if */ + } /* if */ + } else { + /* 'fast' is not a pair. It is either nil, + signifying the end of a list, or this is not a + list. */ + result = fast.is_nil(); + } /* if */ + } else { + /* 'slow' is not a pair. It is either nil, + signifying the end of a list, or this is not a + list. */ + result = slow.is_nil(); + } /* if */ + } /* if */ + } /* while */ + } /* if */ + } /* if */ + return result; + } /* is_list */ + + public static object[] convert_apply_args_to_array2(object[] fixed, object head) { + int len; + int i; + object curr; + object[] result; + + if (!object.is_list(head)) { + result = object.objarr_type_error("'apply' requires a proper list\n"); + } else { + /* Compute the length of the list, adding it to the length of + the fixed array. */ + len = fixed.length; + curr = head; + while (!curr.is_nil()) { + len = len + 1; + curr = curr.pair_cdr(); + } /* while */ + /* Allocate the new array. */ + result = new object[len]; + /* Assign the elements of the fixed array to the result + array. */ + i = 0; + while (i < fixed.length) { + result[i] = fixed[i]; + i = i + 1; + } /* while */ + /* check_assertion(i == fixed.length); */ + /* check_assertion(i <= len); */ + /* check_assertion(i < len || head.is_nil()); */ + /* Assign the elements of the argument list to the result + array. */ + curr = head; + while (i < len) { + result[i] = curr.pair_car(); + i = i + 1; + curr = curr.pair_cdr(); + } /* while */ + } /* if */ + return result; + } /* convert_apply_args_to_array2 */ + + public static object[] convert_apply_args_to_array(object head) { + /* 'head' is the list of parameters to Scheme function 'apply'. + This means that the list was built by the runtime library and + is "safe", i.e. we can skip the is_list check. It also means + that the last element of 'head' is itself an embedded list + (this follows directly from the form of the apply argument list + from r5rs). */ + /* Walk through 'head' and its embedded list, and flatten this out + into a new argument array, which is the return value of the + routine. */ + int len; + int outer_length; + int i; + object curr; + object[] result; + object last; + + /* It is assumed that 'head' is a correct list, since it was built + by the runtime. We avoid the is_list check here for + efficiency. */ + if (/*!object.is_list(head)*/ false) { + result = object.objarr_type_error("'apply' requires a proper list\n"); + } else { + /* Compute the length of the list. */ + len = 0; + curr = head; + /* 'last' is initialized to something here to prevent a + warning from javac. We assume that it will be set in the + loop, or else length will be 0 which is an error. */ + last = head; + while (!curr.is_nil()) { + len = len + 1; + last = curr.pair_car(); + curr = curr.pair_cdr(); + } /* while */ + if (len == 0) { + /* The 'apply' function requires at least one argument -- the + embedded list. */ + result = object.objarr_type_error("'apply' requires at least one argument\n"); + } else { + /* Subtract 1 for the embedded list which was counted above. */ + len = len - 1; + outer_length = len; + /* At this point, 'last' points to the embedded list that will + become the tail of the result array. We need to ensure this + is a proper list before working with it. */ + curr = last; + if (!object.is_list(curr)) { + result = object.objarr_type_error("'apply' requires a proper list\n"); + } else { + /* Now walk through the embedded list and add its elements to + the required length. */ + while (!curr.is_nil()) { + len = len + 1; + curr = curr.pair_cdr(); + } /* while */ + /* Allocate the new array. */ + result = new object[len]; + /* Assign the elements of the argument list to the result + array. */ + curr = head; + i = 0; + while (i < outer_length) { + result[i] = curr.pair_car(); + i = i + 1; + curr = curr.pair_cdr(); + } /* while */ + /* Assign the elements of the embedded argument list to the + result array. */ + /* check_assertion(curr.pair_cdr().is_nil()); */ + curr = curr.pair_car(); + while (i < len) { + result[i] = curr.pair_car(); + i = i + 1; + curr = curr.pair_cdr(); + } /* while */ + } /* if */ + } /* if */ + } /* if */ + return result; + } /* convert_apply_args_to_array */ + + public static object apply_function(object function, object args) + { + object[] argv; + + argv = object.convert_apply_args_to_array(args); + return function.apply(argv); + } /* apply_function */ + + public static int list_plus(object head) + { + /* Assuming that 'head' is the start of a proper list of integer-type + objects, return the sum of the objects. */ + int val; + + val = 0; + while (!head.is_nil()) { + val = val + head.pair_car().int_value(); + head = head.pair_cdr(); + } /* while */ + return val; + } /* list_plus */ + + public static int list_mul(object head) + { + /* Assuming that 'head' is the start of a proper list of integer-type + objects, return the product of the objects. */ + int val; + + val = 1; + while (!head.is_nil()) { + val = val * head.pair_car().int_value(); + head = head.pair_cdr(); + } /* while */ + return val; + } /* list_mul */ + + public static int list_sub(object x, object head) + { + int val; + + if (head.is_nil()) { + val = 0-x.int_value(); + } else { + val = x.int_value(); + while (!head.is_nil()) { + val = val - head.pair_car().int_value(); + head = head.pair_cdr(); + } /* while */ + } /* if */ + return val; + } /* list_sub */ + + public static boolean list_eq(object x, object y, object head) + { + int last; + int curr; + boolean result; + + last = y.int_value(); + result = x.int_value() == last; + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (last == curr); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_eq */ + + public static boolean list_lt(object x, object y, object head) + { + int last; + int curr; + boolean result; + + last = y.int_value(); + result = x.int_value() < last; + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (last < curr); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_lt */ + + public static boolean list_lteq(object x, object y, object head) + { + int last; + int curr; + int ix; + boolean result; + + last = y.int_value(); + ix = x.int_value(); + result = (!(!(ix < last) && !(ix == last))); + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (!(!(last < curr) && !(last == curr))); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_lteq */ + + public static boolean list_gt(object x, object y, object head) + { + int last; + int curr; + int ix; + boolean result; + + last = y.int_value(); + ix = x.int_value(); + result = (!(ix < last) && !(ix == last)); + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (!(last < curr) && !(last == curr)); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_gt */ + + public static boolean list_gteq(object x, object y, object head) + { + int last; + int curr; + boolean result; + + last = y.int_value(); + result = !(x.int_value() < last); + while (result && !head.is_nil()) { + curr = head.pair_car().int_value(); + result = result && (!(last < curr)); + head = head.pair_cdr(); + last = curr; + } /* while */ + return result; + } /* list_gteq */ + + public static int string_to_number(char[] str, int radix) { + int val; + int idx; + int digit; + int c; + int stop; + int power; + boolean negative; + + if (0-1 < radix && radix < 17 && 0 < str.length) { + val = 0; + power = 1; + idx = str.length - 1; + if (str[0] == '-') { + negative = true; + stop = 1; + } else { + negative = false; + stop = 0; + } /* if */ + while (!(idx < stop)) { + c = str[idx]; + if ('/' < c && c < ':') { + digit = c - '0'; + } else { + if ('@' < c && c < 'G') { + digit = c - 'A'; + } else { + if ('`' < c && c < 'g') { + digit = c - 'a'; + } else { + digit = radix; + } /* if */ + } /* if */ + } /* if */ + if (digit < radix) { + val = val + (digit * power); + power = power * radix; + } else { + val = object.int_type_error("in string->number, digit out-of-range\n"); + idx = 0-1; + } /* if */ + idx = idx - 1; + } /* while */ + if (negative) { + val = 0-val; + } else { + } /* if */ + } else { + val = object.int_type_error("in string->number, invalid parameter\n"); + } /* if */ + return val; + } /* string_to_number */ + + public static char[] number_to_string(int val, int radix) { + String digits_string; + char[] digits; + char[] result; + int digits_count; + int iter; + int quotient; + int remainder; + int idx; + boolean negative; + + digits_count = 0; + digits_string = "0123456789abcdef"; + digits = digits_string.toCharArray(); + if (val < 0) { + negative = true; + val = 0-val; + } else { + negative = false; + } /* if */ + if (val == 0) { + result = new char[1]; + result[0] = '0'; + } else { + if (negative) { + digits_count = 1; + } else { + digits_count = 0; + } /* if */ + iter = val; + while (!(iter == 0)) { + quotient = 1; + while (quotient * radix < iter) { quotient = quotient + 1; } + if (iter < quotient * radix) { + quotient = quotient - 1; + } else { + } /* if */ + iter = quotient; + digits_count = digits_count + 1; + } /* while */ + result = new char[digits_count]; + if (negative) { + result[0] = '-'; + } else { + } /* if */ + iter = val; + idx = result.length - 1; + while (!(iter == 0)) { + quotient = 1; + while (quotient * radix < iter) { quotient = quotient + 1; } + if (iter < quotient * radix) { + quotient = quotient - 1; + } else { + } /* if */ + remainder = iter - quotient * radix; + iter = quotient; + result[idx] = digits[remainder]; + idx = idx - 1; + } /* while */ + } /* if */ + return result; + } /* number_to_string */ + + // common ////////////////////////////////////////////////////////// + public boolean eq( object o ) { return this == o; } + public boolean eqv( object o ) { return this.eq( o ); } + public boolean equal( object o ) { return this.eqv( o ); } + + // procedure /////////////////////////////////////////////////////// + public boolean is_proc() { return false; } + public object apply( object[] args ) { return object.obj_type_error("attempt to invoke a non-procedure\n"); } + + // bool //////////////////////////////////////////////////////////// + public boolean is_bool() { return false; } + public boolean bool_value() { return object.bool_type_error("expected a boolean\n"); } + + // int ///////////////////////////////////////////////////////////// + public boolean is_int() { return false; } + public int int_value() { return object.int_type_error("expected an int\n"); } + + // char //////////////////////////////////////////////////////////// + public boolean is_char() { return false; } + public char char_value() { return object.char_type_error("expected a character\n"); } + public boolean char_eq( char c ) { return object.bool_type_error("in char=?, expected a character\n"); } + public boolean char_lt( char c ) { return object.bool_type_error("in char?, expected a character\n"); } + public boolean char_lte( char c ) { return object.bool_type_error("in char<=?, expected a character\n"); } + public boolean char_gte( char c ) { return object.bool_type_error("in char>=?, expected a character\n"); } + public int char_value_as_int() { return object.int_type_error("in char->integer, expected a character\n"); } + + // string ////////////////////////////////////////////////////////// + public boolean is_string() { return false; } + public char[] string_value() { return object.chararr_type_error("expected a string\n"); } + public int string_length() { return object.int_type_error("in string-length, expected a string\n"); } + public char string_ref(int i) { return object.char_type_error("in string-ref, expected a string\n"); } + public object string_set(int i, char c) { return object.obj_type_error("in string-set, expected a string\n"); } + + // symbol ////////////////////////////////////////////////////////// + public boolean is_symbol() { return false; } + public char[] symbol_value() { return object.chararr_type_error("expected a symbol\n"); } + + // vector ////////////////////////////////////////////////////////// + public boolean is_vector() { return false; } + public object[] vector_value() { return object.objarr_type_error("expected a vector\n"); } + public int vector_length() { return object.int_type_error("in vector-length, expected a vector\n"); } + public object vector_ref(int i) { return object.obj_type_error("in vector-ref, expected a vector\n"); } + public object vector_set(int i, object o) { return object.obj_type_error("in vector-set!, expected a vector\n"); } + + // end-of-file ///////////////////////////////////////////////////// + public boolean is_eof() { return false; } + + // nil ///////////////////////////////////////////////////////////// + public boolean is_nil() { return false; } + + // pair //////////////////////////////////////////////////////////// + public boolean is_pair() { return false; } + public object pair_car() { return object.obj_type_error("in car, expected a pair\n"); } + public object pair_cdr() { return object.obj_type_error("in cdr, expected a pair\n"); } + public object pair_set_car( object a ) { return object.obj_type_error("in set-car!, expected a pair\n"); } + public object pair_set_cdr( object a ) { return object.obj_type_error("in set-cdr!, expected a pair\n"); } + + // input-port ////////////////////////////////////////////////////// + public boolean is_input_port() { return false; } + public object read_char() { return object.obj_type_error("in read-char, expected an input-port\n"); } + public object peek_char() { return object.obj_type_error("in peek-char, expected an input-port\n"); } + public boolean char_ready() { return object.bool_type_error("in char-ready?, expected an input-port\n"); } + public object close_input_port() { return object.obj_type_error("in close-input-port, expected an input-port\n"); } + + // output-port ///////////////////////////////////////////////////// + public boolean is_output_port() { return false; } + public object write_char( char c ) { return object.obj_type_error("in write-char, expected an output-port\n"); } + public object close_output_port() { return object.obj_type_error("in close-output-port, expected an output-port\n"); } +} + +class scheme_proc extends object +{ + public boolean is_proc() { return true; } +} + +class scheme_bool extends object +{ + boolean bvalue; + + public scheme_bool() { + bvalue = false; + } + + public scheme_bool(boolean b) { + bvalue = b; + } + + public boolean is_bool() { return true; } + public object bool_const( boolean b ) { bvalue = b; return this; } + public boolean bool_value() { return bvalue; } + public boolean eq(object o) { + boolean value; + if (o.is_bool()) { + value = (o.bool_value() == this.bool_value()); + } else { + value = false; + } + return value; + } +} + +class scheme_int extends object +{ + int ivalue; + + public scheme_int() { + ivalue = 0; + } + + public scheme_int( int i ) { + ivalue = i; + } + + public boolean is_int() { return true; } + public object int_const( int i ) { ivalue = i; return this; } + public int int_value() { return ivalue; } +} + +class scheme_char extends object +{ + char cvalue; + + public scheme_char() { + cvalue = '\0'; + } + + public scheme_char( char c ) { + cvalue = c; + } + + public scheme_char( int i ) { + cvalue = scheme_io_interface.make_char(i); + } + + public object char_const(char c) { cvalue = c; return this; } + + public boolean is_char() { return true; } + public char char_value() { return cvalue; } + public boolean char_eq( char c ) { return cvalue == c; } + public boolean char_lt( char c ) { return cvalue < c; } + public boolean char_gt( char c ) { + boolean value; + + if (cvalue < c) { + value = false; + } else { + if (cvalue == c) { + value = false; + } else { + value = true; + } + } + return value; + } + public boolean char_lte( char c ) { + boolean value; + + if (cvalue < c) { + value = true; + } else { + if (cvalue == c) { + value = true; + } else { + value = false; + } + } + return value; + } + public boolean char_gte( char c ) { return !(cvalue < c); } + public int char_value_as_int() { return 0 + cvalue; } +} + +class scheme_string extends object +{ + char[] svalue; + + public scheme_string() { + svalue = new char[0]; + } + + public scheme_string( char[] s ) { + svalue = s; + } + + public scheme_string( int k, char c ) { + int i; + + svalue = new char[k]; + i = 0; + while (i < k) { + svalue[i] = c; + i = i + 1; + } + } + + public boolean is_string() { return true; } + public char[] string_value() { + return svalue; + } + public int string_length() { + return svalue.length; + } + public char string_ref(int i) { + return svalue[i]; + } +} + +class scheme_symbol extends object +{ + char[] svalue; + + public scheme_symbol() { + svalue = new char[0]; + } + + public scheme_symbol( char[] s ) { + svalue = s; + } + + public boolean is_symbol() { return true; } + public char[] symbol_value() { return svalue; } +} + +class scheme_eof extends object +{ + public boolean is_eof() { return true; } +} + +class scheme_nil extends object +{ + public boolean eq(object o) { return o.is_nil(); } + public boolean is_nil() { return true; } +} + +class scheme_vector extends object +{ + object[] value; + + public scheme_vector( int n ) { + value = new object[n]; + } + + public scheme_vector( int n, object o ) { + int i; + value = new object[n]; + i = 0; + while (i < n) { + value[i] = o; + i = i + 1; + } + } + + public boolean is_vector() { return true; } + public object[] vector_value() { return value; } + public int vector_length() { return value.length; } + public object vector_ref(int i) { return value[i]; } + public object vector_set(int i, object o) { value[i] = o; return o; } +} + +class scheme_pair extends object +{ + object car; + object cdr; + + public scheme_pair( object a, object d ) { + car = a; + cdr = d; + } /* scheme_pair */ + + public boolean is_pair() { return true; } + + public object pair_car() { return car; } + public object pair_cdr() { return cdr; } + + public object pair_set_car( object a ) { car = a; return a; } + public object pair_set_cdr( object a ) { cdr = a; return a; } +} + +class scheme_io_interface +{ +#if TESTING + public static int open_file(char[] fname, int len, int read) { + return -1; + } /* open_file */ + public static int close_file(int file) { + throw new Error(); + } /* close_file */ + public static int read_file(int file) { + throw new Error(); + } /* read_file */ + public static int write_file(int file, char c) { + throw new Error(); + } /* write_file */ + public static char make_char(int ch) { + return (char)ch; + } /* make_char */ + public static object print_char(char c) { + System.out.println(c); + return null; + } /* print_char */ +#else + __sasm_impl public static int open_file( char[] fname, int len, int read ) + = sasm_scheme_open_file; + __sasm_impl public static int close_file( int file ) + = sasm_scheme_close_file; + __sasm_impl public static int read_file( int file ) + = sasm_scheme_read_file; + __sasm_impl public static int write_file( int file, char c ) + = sasm_scheme_write_file; + __sasm_impl public static char make_char( int ch ) + = sasm_scheme_make_char; + __sasm_impl public static object print_char( char c ) + = sasm_scheme_print_char; +#endif /* TESTING */ +} + +class scheme_input_port extends object +{ + int f; + scheme_eof eof; + boolean peeked; + object peeked_char; + + public scheme_input_port() { + char[] fname; + + fname = new char[0]; + f = scheme_io_interface.open_file(fname, 0, 1); + eof = new scheme_eof(); + peeked = false; + peeked_char = eof; + } + + public scheme_input_port( char[] fname ) { + f = scheme_io_interface.open_file(fname, fname.length, 1); + eof = new scheme_eof(); + peeked = false; + peeked_char = eof; + } /* scheme_input_port */ + + public boolean is_input_port() { + return true; + } /* is_input_port */ + + public object peek_char() { + object result; + + if (peeked) { + result = peeked_char; + } else { + result = this.read_char(); + peeked_char = result; + peeked = true; + } + return result; + } /* peek_char */ + + public boolean char_ready() { + return true; + } /* char_ready */ + + public object read_char() { + object result; + int c; + + if (f == 0) { + result = eof; + } else { + if (peeked) { + peeked = false; + result = peeked_char; + } else { + c = scheme_io_interface.read_file(f); + if (c < 0) { + result = eof; + } else { + result = new scheme_char( scheme_io_interface.make_char(c) ); + } + } + } + return result; + } /* read_char */ + + public object close_input_port() { + int c; + + if (f == 0) { + /* nothing */ + } else { + c = scheme_io_interface.close_file(f); + f = 0; + } /* if */ + return eof; + } /* close_input_port */ +} /* class scheme_input_port */ + +class scheme_output_port extends object +{ + int f; + + public scheme_output_port() { + char[] fname; + + fname = new char[0]; + f = scheme_io_interface.open_file(fname, 0, 0); + } /* scheme_output_port */ + + public scheme_output_port( char[] fname ) { + f = scheme_io_interface.open_file(fname, fname.length, 0); + } /* scheme_output_port */ + + public boolean is_output_port() { return true; } + + public object write_char( char c ) { + int dontcare; + + if (f == 0) { + /* nothing */ + } else { + dontcare = scheme_io_interface.write_file(f, c); + } /* if */ + return this; + } /* write_char */ + + public object close_output_port() { + int dontcare; + + if (f == 0) { + /* nothing */ + } else { + dontcare = scheme_io_interface.close_file(f); + f = 0; + } /* if */ + return this; + } /* close_output_port */ +} /* class scheme_output_port */ diff --git a/src/rtl/spim-main.s b/src/rtl/spim-main.s new file mode 100644 index 0000000..40ce92c --- /dev/null +++ b/src/rtl/spim-main.s @@ -0,0 +1,28 @@ + .text + .globl main + .globl _gc_root_stack_limit + +main: la $a0, _gc_root_stack_limit # initialize the top-of-stack pointer for GC + sw $sp, 0($a0) + + li $a0, 47104 # initialize the heap for gc + sub $sp, $sp, 4 # 41704 words = 188416 bytes = arg1 + sw $a0, 0($sp) + + li $a0, 268509184 # 0x1010000 + 8192 - start of the heap = arg0 + sub $sp, $sp, 4 + sw $a0, 0($sp) + + la $a0, _mm_heap_add_area + jal $a0 + + la $a0, _sasm_entry # jump to main + jal $a0 + li $v0, 10 + syscall + + .data +_gc_root_stack_limit: + .word 0 + + \ No newline at end of file diff --git a/src/run-ts.scm b/src/run-ts.scm new file mode 100644 index 0000000..3e90655 --- /dev/null +++ b/src/run-ts.scm @@ -0,0 +1,14 @@ +;; run-ts.scm +;; +;; Compatibility interface for TinyScheme 1.41. Currently does not +;; work because TinyScheme does not support +;; define-syntax/syntax-rules. I'm just keeping this around for old +;; time's sake. Take a look at needc.scm instead. + + +(load "compat/tinyscheme.scm") +(load "need.scm") +(need scheme/tag) +(need scheme/genproc) +(define *argv* (list->vector *args*)) +(load (vector-ref *argv* 0)) diff --git a/src/sasm-interp-mips.scm b/src/sasm-interp-mips.scm new file mode 100644 index 0000000..6a02b25 --- /dev/null +++ b/src/sasm-interp-mips.scm @@ -0,0 +1,8 @@ +(need sasm/sasm-interp-spec) +(need sasm/sasm-tx) +(need sasm/sasm-mips) + +(sasm-interp-specialize! 'mips) + +(need sasm/sasm-interp) + diff --git a/src/sasm-interp-ts.scm b/src/sasm-interp-ts.scm new file mode 100644 index 0000000..dd89eaa --- /dev/null +++ b/src/sasm-interp-ts.scm @@ -0,0 +1,3 @@ +(need compat/tinyscheme) +(need scheme/tag) +(need sasm-interp) diff --git a/src/sasm-interp-x86.scm b/src/sasm-interp-x86.scm new file mode 100644 index 0000000..7b6110b --- /dev/null +++ b/src/sasm-interp-x86.scm @@ -0,0 +1,8 @@ +(need sasm/sasm-interp-spec) +(need sasm/sasm-tx) +(need sasm/sasm-nasmx86) + +(sasm-interp-specialize! 'x86) + +(need sasm/sasm-interp) + diff --git a/src/sasm-interp.scm b/src/sasm-interp.scm new file mode 100644 index 0000000..6488510 --- /dev/null +++ b/src/sasm-interp.scm @@ -0,0 +1 @@ +(need sasm/sasm-interp) diff --git a/src/sasm-mips.scm b/src/sasm-mips.scm new file mode 100644 index 0000000..305fd6c --- /dev/null +++ b/src/sasm-mips.scm @@ -0,0 +1,5 @@ +(need sasm/sasm) +(need sasm/sasm-mips) +(sasm-set-target-mips!) +(sasm-set-mips-hw-params!) +(sasm-assembler-main *argv*) diff --git a/src/sasm-opt-mips.scm b/src/sasm-opt-mips.scm new file mode 100644 index 0000000..2ded4fa --- /dev/null +++ b/src/sasm-opt-mips.scm @@ -0,0 +1,10 @@ +(need sasm/sasm-regalloc) +(need sasm/sasm-tx) +(need sasm/sasm-mips) +(need sasm/sasm-opt) + +(set! *sasm-enable-regalloc* #t) +(sasm-set-target-mips!) +(sasm-set-mips-hw-params!) + +(sasm-invoke-optimizer *argv*) diff --git a/src/sasm-opt-ts.scm b/src/sasm-opt-ts.scm new file mode 100644 index 0000000..2d1fc91 --- /dev/null +++ b/src/sasm-opt-ts.scm @@ -0,0 +1,3 @@ +(need compat/tinyscheme) +(need scheme/tag) +(need sasm-opt) diff --git a/src/sasm-opt.dep b/src/sasm-opt.dep new file mode 100644 index 0000000..a364247 --- /dev/null +++ b/src/sasm-opt.dep @@ -0,0 +1,79 @@ +# generated by needc 01-20-2019 0.3 + +deps_of_sasm_opt=\ + util/counting.scm \ + util/matrix.scm \ + util/list.scm \ + util/vector.scm \ + sasm/fastset.scm \ + algo/graph.scm \ + sasm/fastgraph.scm \ + util/string.scm \ + scheme/tag.scm \ + sasm/sasm-tracing.scm \ + sasm/parse/syntax.scm \ + sasm/sasm-ast.scm \ + sasm/parse/extern.scm \ + pat/pat.scm \ + sasm/parse/util.scm \ + sasm/parse/program.scm \ + sasm/parse/member.scm \ + sasm/parse/data-entry.scm \ + sasm/parse/symconst-entry.scm \ + sasm/parse/register-operand.scm \ + sasm/parse/constant-operand.scm \ + sasm/parse/lvalue-operand.scm \ + sasm/parse/operand.scm \ + sasm/parse/operation.scm \ + sasm/parse/instruction.scm \ + sasm/parse/statement.scm \ + sasm/sasm-visitor.scm \ + sasm/sasm-dataflow.scm \ + sasm/sasm-regalloc.scm \ + sasm/sasm-parse.scm \ + sasm/sasm-analyze.scm \ + util/format.scm \ + util/filesystem.scm \ + sasm/sasm-core.scm \ + sasm/machdesc.scm \ + sasm/tx/assemble.scm \ + sasm/tx/config.scm \ + sasm/tx/registers.scm \ + sasm/tx/regrule.scm \ + sasm/tx/labels.scm \ + sasm/tx/rewrite.scm \ + sasm/tx/emit.scm \ + sasm/tx/main.scm \ + sasm/tx/globals.scm \ + sasm/tx/context.scm \ + sasm/tx/read.scm \ + sasm/tx/util.scm \ + sasm/tx/symconst.scm \ + sasm/tx/stmt.scm \ + sasm/sasm-tx.scm \ + sasm/sasm-insel.scm \ + sasm/nasmx86/util.scm \ + sasm/nasmx86/binop.scm \ + sasm/nasmx86/interp.scm \ + sasm/nasmx86/labels.scm \ + sasm/nasmx86/control.scm \ + sasm/nasmx86/compare.scm \ + sasm/nasmx86/stack.scm \ + sasm/nasmx86/store-array.scm \ + sasm/nasmx86/load-array.scm \ + sasm/nasmx86/call.scm \ + sasm/nasmx86/return.scm \ + sasm/nasmx86/arithmetic.scm \ + sasm/nasmx86/mul.scm \ + sasm/nasmx86/bitwise-const.scm \ + sasm/nasmx86/shift.scm \ + sasm/nasmx86/data.scm \ + sasm/nasmx86/preamble.scm \ + sasm/nasmx86/debug.scm \ + sasm/nasmx86/base.scm \ + sasm/nasmx86/machine.scm \ + util/output-file.scm \ + sasm/sasm-nasmx86.scm \ + sasm/sasm-opt.scm \ + # 74 dependencies listed + diff --git a/src/sasm-opt.scm b/src/sasm-opt.scm new file mode 100644 index 0000000..d957511 --- /dev/null +++ b/src/sasm-opt.scm @@ -0,0 +1,21 @@ +(need sasm/sasm-regalloc) +(need sasm/sasm-tx) +(need sasm/sasm-nasmx86) +(need sasm/sasm-opt) + +;; Set optimizer parameters ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Enable the register allocator. +(set! *sasm-enable-regalloc* #t) +;; Disable dataflow analysis and related optimizations (currently expensive). +(set! *sasm-enable-only-regalloc* #t) +;; Do not attempt to allocate temporaries in registers; always use locals. +(set! *sasm-all-temps-are-locals* #t) +;; Do not fold linear instructions into trees to improve instruction +;; selection. +(set! *sasm-fold-instruction-tree* #f) + +;; Set target parameters ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(sasm-set-target-x86!) +(sasm-set-x86-hw-params!) + +(sasm-invoke-optimizer *argv*) diff --git a/src/sasm-ts.scm b/src/sasm-ts.scm new file mode 100644 index 0000000..e6727b1 --- /dev/null +++ b/src/sasm-ts.scm @@ -0,0 +1,3 @@ +(need compat/tinyscheme) +(need scheme/tag) +(need sasm) diff --git a/src/sasm-util.scm b/src/sasm-util.scm new file mode 100644 index 0000000..1c3fd10 --- /dev/null +++ b/src/sasm-util.scm @@ -0,0 +1,75 @@ +;; sasm-util.scm +;; +;; A command-line tool that is used to run the sasm analysis engine +;; on sasm source files and produce useful messages to the console. + +(need util/list) +(need util/string) +(need util/filesystem) +(need util/io) +(need sasm/sasm-machine) +(need sasm/sasm-eval) +(need sasm/sasm-interp-spec) +(need sasm/sasm-tx) +(need sasm/sasm-ast) +(need sasm/sasm-visitor) +(need sasm/sasm-analyze) +(need sasm/sasm-parse) +(need sasm/sasm-rewrite) +(need sasm/sasm-codegen) + +(define *sasm-util-output-port* #f) +(define (sasm-util-output-port) + (if *sasm-util-output-port* + *sasm-util-output-port* + (current-output-port))) + +(define (display-symbol-list title symbols) + (display title (sasm-util-output-port)) + (for-each (lambda (x) + (display " " (sasm-util-output-port)) + (write x (sasm-util-output-port))) + symbols) + (newline (sasm-util-output-port))) + +(define (process-file file) + (let ((code (read-file-fully file))) + (let ((ast (sasm-parse-program code))) + (if (not ast) + (error "SASM parse error in file " file) + (let ((externs (sasm-program-extern-symbols ast)) + (defined (sasm-program-defined-symbols ast)) + (referenced (sasm-program-referenced-symbols ast))) + (if (not (sasm-program-analyze-symbols! "main" ast)) + (error "One or more errors encountered")) + (let* ((rewrite (sasm-rewrite-ast ast)) + (rewrite-ast (sasm-parse-program rewrite))) + (display-symbol-list ";; externs:" externs) + (display-symbol-list ";; defined:" defined) + (display-symbol-list ";; referenced:" referenced) + (newline (sasm-util-output-port)) + (newline (sasm-util-output-port)) + (for-each (lambda (code) + (sasm-pretty-print code (sasm-util-output-port)) + (newline (sasm-util-output-port))) + rewrite) + )))))) + +(define (command-line args) + (define (iter files args) + (cond + ((null? args) + (for-each process-file (reverse files))) + (else + (let ((arg (car args)) + (rest (cdr args))) + (cond + ((starts-with? arg "--out=") + (set! *sasm-util-output-port* + (open-output-file (string-strip-prefix arg "--out="))) + (iter files rest)) + (else + (iter (cons arg files) rest))))))) + (iter '() args)) + +(command-line (cdr (vector->list *argv*))) diff --git a/src/sasm.dep b/src/sasm.dep new file mode 100644 index 0000000..3156576 --- /dev/null +++ b/src/sasm.dep @@ -0,0 +1,79 @@ +# generated by needc 01-20-2019 0.3 + +deps_of_sasm=\ + util/counting.scm \ + util/list.scm \ + util/string.scm \ + util/matrix.scm \ + util/vector.scm \ + sasm/fastset.scm \ + algo/graph.scm \ + sasm/fastgraph.scm \ + sasm/sasm-dataflow.scm \ + sasm/sasm-tx.scm \ + sasm/sasm-tracing.scm \ + sasm/sasm-insel.scm \ + scheme/tag.scm \ + sasm/parse/syntax.scm \ + sasm/sasm-ast.scm \ + sasm/parse/extern.scm \ + pat/pat.scm \ + sasm/parse/util.scm \ + sasm/parse/program.scm \ + sasm/parse/member.scm \ + sasm/parse/data-entry.scm \ + sasm/parse/symconst-entry.scm \ + sasm/parse/register-operand.scm \ + sasm/parse/constant-operand.scm \ + sasm/parse/lvalue-operand.scm \ + sasm/parse/operand.scm \ + sasm/parse/operation.scm \ + sasm/parse/instruction.scm \ + sasm/parse/statement.scm \ + sasm/sasm-visitor.scm \ + sasm/sasm-regalloc.scm \ + sasm/sasm-parse.scm \ + sasm/sasm-analyze.scm \ + util/format.scm \ + util/filesystem.scm \ + sasm/sasm-core.scm \ + sasm/machdesc.scm \ + sasm/tx/assemble.scm \ + sasm/tx/config.scm \ + sasm/tx/registers.scm \ + sasm/tx/regrule.scm \ + sasm/tx/labels.scm \ + sasm/tx/rewrite.scm \ + sasm/tx/emit.scm \ + sasm/tx/main.scm \ + sasm/tx/globals.scm \ + sasm/tx/context.scm \ + sasm/tx/read.scm \ + sasm/tx/util.scm \ + sasm/tx/symconst.scm \ + sasm/tx/stmt.scm \ + util/output-file.scm \ + sasm/nasmx86/util.scm \ + sasm/nasmx86/binop.scm \ + sasm/nasmx86/interp.scm \ + sasm/nasmx86/labels.scm \ + sasm/nasmx86/control.scm \ + sasm/nasmx86/compare.scm \ + sasm/nasmx86/stack.scm \ + sasm/nasmx86/store-array.scm \ + sasm/nasmx86/load-array.scm \ + sasm/nasmx86/call.scm \ + sasm/nasmx86/return.scm \ + sasm/nasmx86/arithmetic.scm \ + sasm/nasmx86/mul.scm \ + sasm/nasmx86/bitwise-const.scm \ + sasm/nasmx86/shift.scm \ + sasm/nasmx86/data.scm \ + sasm/nasmx86/preamble.scm \ + sasm/nasmx86/debug.scm \ + sasm/nasmx86/base.scm \ + sasm/nasmx86/machine.scm \ + sasm/sasm.scm \ + sasm/sasm-nasmx86.scm \ + # 74 dependencies listed + diff --git a/src/sasm.scm b/src/sasm.scm new file mode 100644 index 0000000..92c683d --- /dev/null +++ b/src/sasm.scm @@ -0,0 +1,5 @@ +(need sasm/sasm) +(need sasm/sasm-nasmx86) +(sasm-set-target-x86!) +(sasm-set-x86-hw-params!) +(sasm-assembler-main *argv*) diff --git a/src/sasm/fastgraph.scm b/src/sasm/fastgraph.scm new file mode 100644 index 0000000..4864618 --- /dev/null +++ b/src/sasm/fastgraph.scm @@ -0,0 +1,23 @@ +;; sasm/fastgraph.scm +;; Fast graph primitives + +(need util/counting) +(need util/matrix) +(need util/list) + +;; fast graph-processing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (graph->adj-matrix graph =?) + (let ((elements (graph-elements graph)) + (adj-matrix (square-matrix (length graph) #f))) + (define (index obj) (index-of obj =? elements)) + (for-each (lambda (adj) + (let ((parent (index (car adj)))) + (for-each (lambda (child) + (matrix-set! adj-matrix + parent + (index child) + #t)) + (cdr adj)))) + graph) + adj-matrix)) diff --git a/src/sasm/fastset.scm b/src/sasm/fastset.scm new file mode 100644 index 0000000..a7d4ca7 --- /dev/null +++ b/src/sasm/fastset.scm @@ -0,0 +1,109 @@ +;; sasm/fastset.scm +;; +;; This was originally a relatively "fast" set primitives in terms of +;; arbitrary-precision bitwise integer arithmetic. +;; +;; However, the arbitrary-precision bitwise integer arithmetic was +;; part of a specific and now defunct scheme implementation that is no +;; longer a good dependency. Therefore the code was rewritten in a +;; much slower fashion using strings to implement a poor version of +;; arbitrary-precision bitwise arithmetic. + +(define (fastset-importer symbolic-set) + (let ((len (length symbolic-set))) + (vector + (lambda () (make-string len #\0)) + (lambda (symbol) + (let ((match (member symbol symbolic-set))) + (if (not match) + (error "Unrecognized symbol -- fastset" symbol symbolic-set)) + (- len (length match))))))) + +(define (fastset-exporter importer symbolic-set) + (define (get-index symbol) + ((vector-ref importer 1) symbol)) + (lambda (fastset) + (let loop ((symbols symbolic-set) + (result '())) + (if (null? symbols) + (reverse result) + (let ((sym (car symbols))) + (if (char=? (string-ref fastset (get-index sym)) #\1) + (loop (cdr symbols) (cons sym result)) + (loop (cdr symbols) result))))))) + +(define (fastset-collapse importer symset) + (define (make-fastset) + ((vector-ref importer 0))) + (define (get-index symbol) + ((vector-ref importer 1) symbol)) + (let loop ((result (make-fastset)) + (rest symset)) + (if (null? rest) + result + (begin (string-set! result (get-index (car rest)) #\1) + (loop result (cdr rest)))))) + +(define (fastset-expand exporter fastset) + (if (not (string? fastset)) + (error "fastset-expand, not a fastset " fastset)) + (exporter fastset)) + +(define (fastset-union fastset-a fastset-b) + (define (union a b) + (if (or (char=? a #\1) + (char=? b #\1)) + #\1 + #\0)) + (if (not (string? fastset-a)) + (error "fastset-union, fastset-a not a fastset " fastset-a)) + (if (not (string? fastset-b)) + (error "fastset-union, fastset-b not a fastset " fastset-b)) + (let* ((len (string-length fastset-a)) + (result (make-string len #\0))) + (let loop ((index 0)) + (if (>= index len) + result + (begin (string-set! result + index + (union (string-ref fastset-a index) + (string-ref fastset-b index))) + (loop (+ 1 index))))))) +; (bitwise-ior fastset-a fastset-b)) + +(define (fastset-subtract fastset-a fastset-b) + (define (subtract a b) + (if (and (char=? a #\1) + (char=? b #\0)) + #\1 + #\0)) + (if (not (string? fastset-a)) + (error "fastset-subtract, fastset-a not a fastset " fastset-a)) + (if (not (string? fastset-b)) + (error "fastset-subtract, fastset-b not a fastset " fastset-b)) + (let* ((len (string-length fastset-a)) + (result (make-string len #\0))) + (let loop ((index 0)) + (if (>= index len) + result + (begin (string-set! result + index + (subtract (string-ref fastset-a index) + (string-ref fastset-b index))) + (loop (+ 1 index))))))) +; (bitwise-and fastset-a (bitwise-not fastset-b))) + +(define (fastset-equal? fastset-a fastset-b) + (if (not (string? fastset-a)) + (error "fastset-equal?, fastset-a not a fastset " fastset-a)) + (if (not (string? fastset-b)) + (error "fastset-equal?, fastset-b not a fastset " fastset-b)) + (string=? fastset-a fastset-b)) + +; unused +;(define (fastset-intersect fastset-a fastset-b) +; (bitwise-and fastset-a fastset-b)) + +;(define (fastset-subset? fastset-a fastset-b) +; (= 0 (fastset-subtract fastset-a fastset-b))) + diff --git a/src/sasm/fp.scm b/src/sasm/fp.scm new file mode 100644 index 0000000..19aad8f --- /dev/null +++ b/src/sasm/fp.scm @@ -0,0 +1,36 @@ +;; sasm/fp.scm +;; Floating point routines for SASM + +;; S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF +;; 0 1 8 9 31 + +(define (ieee754-decompose fp) + (let* ((neg (negative? fp)) + (val (abs fp)) + (exponent (let loop ((v val) (e 0)) + (cond ((or (>= e 128) (<= e -127)) e) + ((< 1 v 2) e) + ((< v 1) (loop (* v 2) (- e 1))) + ((> v 1) (loop (/ v 2) (+ e 1))) + (else e)))) + (fraction (/ val (expt 2 exponent)))) + (if (= -127 exponent) + (list (if neg 1 0) exponent (+ (/ fraction 2) 1)) + (list (if neg 1 0) exponent fraction)))) + +(define (ieee754-pack-fraction f) + (let loop ((f (* 2 (- f 1))) + (i 0) + (e (expt 2 22)) + (v 0)) + (cond ((> i 22) v) + ((< f 1) (loop (* 2 f) (+ i 1) (/ e 2) v)) + (else (loop (* 2 (- f 1)) (+ i 1) (/ e 2) (+ v e)))))) + +(define (ieee754-pack decomp) + (+ (* (expt 2 31) (list-ref decomp 0)) + (* (expt 2 23) (+ 127 (list-ref decomp 1))) + (ieee754-pack-fraction (list-ref decomp 2)))) + +(define (ieee754->integer fp) + (ieee754-pack (ieee754-decompose fp))) diff --git a/src/sasm/machdesc.scm b/src/sasm/machdesc.scm new file mode 100644 index 0000000..9f626a2 --- /dev/null +++ b/src/sasm/machdesc.scm @@ -0,0 +1,41 @@ +;; machdesc.scm +;; machine description syntax and functions + +(define (machine-description . args) + args) + +;; instruction syntax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-syntax instruction + (syntax-rules (input-pattern rewrite-rule transform insel-rewrite-rule) + + ((instruction (input-pattern ) + (rewrite-rule ( ( ) ...) ...)) + (instruction (input-pattern ) + (rewrite-rule ( ( ) ...) ...) + (side-effects))) + + ((instruction (input-pattern ) + (rewrite-rule ( ) ...)) + (instruction (input-pattern ) + (rewrite-rule ( ( ) ...)))) + + ((instruction (input-pattern ) + (rewrite-rule ( ( ) ...) ...) + (side-effects ...)) + (list + (list (list (quasiquote ) (cons ' ) ...) ...) + (list ' ...) + #f)) + + ((instruction (input-pattern ) + (rewrite-rule ( ( ) ...) ...) + (side-effects ...) + (insel-rewrite-rule ...)) + (list + (list (list (quasiquote ) (cons ' ) ...) ...) + (list ' ...) + (list (quasiquote ) ...))) + + )) + diff --git a/src/sasm/nasmx86/arithmetic.scm b/src/sasm/nasmx86/arithmetic.scm new file mode 100644 index 0000000..ed6bebd --- /dev/null +++ b/src/sasm/nasmx86/arithmetic.scm @@ -0,0 +1,26 @@ +(need sasm/machdesc) + +(define (nasm-x86-arithmetic) + (machine-description + ;; arithmetic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(assign (,register? dest) (op add) (,register? dest) (const 1))) + (rewrite-rule "inc ~" (dest register))) + + (instruction (input-pattern `(assign (,register? dest) (op sub) (,register? dest) (const 1))) + (rewrite-rule "dec ~" (dest register))) + + (instruction (input-pattern `(assign (,register? dest) (op add-pointer) (,register? op-a) (const (,intconst? op-b)))) + (rewrite-rule ((assign (replace dest) (replace op-a)) (dest sym-register) (op-a sym-register)) + ("add ~, ~" + (dest register) + (op-b (lambda (x) (* 4 x)))))) + + (instruction (input-pattern `(assign (,register? dest) (op sub-pointer) (,register? op-a) (const (,intconst? op-b)))) + (rewrite-rule ((assign (replace dest) (replace op-a)) (dest sym-register) (op-a sym-register)) + ("sub ~, ~" + (dest register) + (op-b (lambda (x) (* 4 x)))))) + + )) + diff --git a/src/sasm/nasmx86/base.scm b/src/sasm/nasmx86/base.scm new file mode 100644 index 0000000..c44ff68 --- /dev/null +++ b/src/sasm/nasmx86/base.scm @@ -0,0 +1,20 @@ +(define (nasm-x86-machine-base) + (append + (nasm-x86-interp-support) + (nasm-x86-machine-labels) + (nasm-x86-control) + (nasm-x86-compare) + (nasm-x86-stack) + (nasm-x86-store-array) + (nasm-x86-load-array) + (nasm-x86-call) + (nasm-x86-return) + (nasm-x86-arithmetic) + (nasm-x86-multiply) + (nasm-x86-bitwise-const) + (nasm-x86-rshift) + (nasm-x86-data) + (nasm-x86-preamble) + (nasm-x86-debug) + )) + diff --git a/src/sasm/nasmx86/binop.scm b/src/sasm/nasmx86/binop.scm new file mode 100644 index 0000000..7eb63d4 --- /dev/null +++ b/src/sasm/nasmx86/binop.scm @@ -0,0 +1,98 @@ +(need sasm/machdesc) + +(define (nasm-x86-twoarg-binop-deref sasm-op mach-op) + (machine-description + + ;; add eax, [ebx+N] ; N can be 0 + (instruction (input-pattern `(assign (,register? dest) + (op ,sasm-op) + (,register? op-a) + (result (op load-array) + (,register? ptr) + (const (,intconst? offset))))) + (rewrite-rule ((assign (replace dest) (replace op-a)) (dest sym-register) (op-a sym-register)) + (,(format "~ ~, [~~~]" mach-op "~" "~" "~" "~") + (dest register) + (ptr register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset)))) + + ;; add eax, [ebx+4*ecx] + (instruction (input-pattern `(assign (,register? dest) + (op ,sasm-op) + (,register? op-a) + (result (op load-array) + (,register? ptr) + (,register? offset)))) + (rewrite-rule ((assign (replace dest) (replace op-a)) (dest sym-register) (op-a sym-register)) + (,(format "~ ~, [~~~]" mach-op "~" "~" "~" "~") + (dest register) + (ptr register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset)))) + + ;; add [eax+N], ebx + (instruction (input-pattern `(perform (op store-array) + (,register? ptr) + (const (,intconst? offset)) + (result (op ,sasm-op) + (result (op load-array) + (,register? ptr) + (const (,intconst? offset))) + (,register? op-b)))) + (rewrite-rule (,(format "~ [~~~], ~" mach-op "~" "~" "~" "~") + (ptr register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (op-b register)))) + + ;; add [eax+4*ebx], ecx + (instruction (input-pattern `(perform (op store-array) + (,register? ptr) + (,register? offset) + (result (op ,sasm-op) + (result (op load-array) + (,register? ptr) + (,register? offset)) + (,register? op-b)))) + (rewrite-rule (,(format "~ [~~~], ~" mach-op "~" "~" "~" "~") + (ptr register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (op-b register)))) + + )) + +(define (nasm-x86-twoarg-binop-direct sasm-op mach-op) + (machine-description + + + ;; add eax, N + (instruction (input-pattern `(assign (,register? dest) (op ,sasm-op) (,register? op-a) (const (,intconst? op-b)))) + (rewrite-rule ((assign (replace dest) (replace op-a)) (dest sym-register) (op-a sym-register)) + (,(format "~ ~, ~" mach-op "~" "~") + (dest register) + (op-b intconst)))) + + ;; add eax, ebx [special case of (assign (reg dest) (op add) (reg dest) (reg op))] + (instruction (input-pattern `(assign (,register? dest) (op ,sasm-op) (,register? dest) (,register? operand))) + (rewrite-rule (,(format "~ ~, ~" mach-op "~" "~") + (dest register) + (operand register)))) + + ;; add eax, ebx [general case] + (instruction (input-pattern `(assign (,register? dest) (op ,sasm-op) (,const-or-reg? op-a) (,const-or-reg? op-b))) + (rewrite-rule ((assign (replace dest) (replace op-a)) (dest sym-register) (op-a sym-const-or-reg)) + (,(format "~ ~, ~" mach-op "~" "~") + (dest register) + (op-b const-or-reg))) + (side-effects) + (insel-rewrite-rule (assign (replace-temp x) (replace op-b)) + (assign (replace dest) (replace op-a)) + (assign (replace dest) (op ,sasm-op) (replace dest) (replace-temp x)))) + + )) + +(define (nasm-x86-standard-twoarg-binop sasm-op mach-op) + (append (nasm-x86-twoarg-binop-deref sasm-op mach-op) + (nasm-x86-twoarg-binop-direct sasm-op mach-op))) diff --git a/src/sasm/nasmx86/bitwise-const.scm b/src/sasm/nasmx86/bitwise-const.scm new file mode 100644 index 0000000..3bcd5df --- /dev/null +++ b/src/sasm/nasmx86/bitwise-const.scm @@ -0,0 +1,20 @@ +(need sasm/machdesc) + +(define (nasm-x86-bitwise-const) + (machine-description + ;; bit-shift operations, constant offset + + (instruction (input-pattern `(assign (,register? dest) (op bit-lshift) (,register? src) (const (,intconst? n-bits)))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ("sal ~, ~" (dest register) (n-bits intconst)))) + + (instruction (input-pattern `(assign (,register? dest) (op bit-rshift) (,register? src) (const (,intconst? n-bits)))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ("shr ~, ~" (dest register) (n-bits intconst)))) + + (instruction (input-pattern `(assign (,register? dest) (op bit-arith-rshift) (,register? src) (const (,intconst? n-bits)))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ("sar ~, ~" (dest register) (n-bits intconst)))) + + )) + diff --git a/src/sasm/nasmx86/call.scm b/src/sasm/nasmx86/call.scm new file mode 100644 index 0000000..7071a8e --- /dev/null +++ b/src/sasm/nasmx86/call.scm @@ -0,0 +1,25 @@ +(need sasm/machdesc) + +(define (nasm-x86-call) + (machine-description + ;; calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; primary + (instruction (input-pattern `(perform (op call) (const (,label? label)))) + (rewrite-rule ("call ~" (label label)))) + + (instruction (input-pattern `(perform (op call) (label (,label? label)))) + (rewrite-rule ("call ~" (label label)))) + +;; primary? + (instruction (input-pattern `(perform (op call) (,register? pointer))) + (rewrite-rule ("call ~" (pointer register)))) + + (instruction (input-pattern `(perform (op tail-call) (const (,label? label)) (const (,intconst? in)) (const (,intconst? out)))) + (rewrite-rule ("call ~" (label label)))) + + (instruction (input-pattern `(perform (op tail-call) (,register? pointer) (const (,intconst? in)) (const (,intconst? out)))) + (rewrite-rule ("call ~" (pointer register)))) + + )) + diff --git a/src/sasm/nasmx86/compare.scm b/src/sasm/nasmx86/compare.scm new file mode 100644 index 0000000..9d1a45a --- /dev/null +++ b/src/sasm/nasmx86/compare.scm @@ -0,0 +1,46 @@ +(need sasm/machdesc) + +(define (nasm-x86-compare) + (machine-description + ;; flags/booleans ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(test (op nonzero) (,register? reg))) + (rewrite-rule ("cmp ~, 0" (reg register)))) + + (instruction (input-pattern `(assign (,register? dest) (op less-than) (,register? op-a) (const (,intconst? op-b)))) + (rewrite-rule ("cmp ~, ~" (op-a register) (op-b intconst)) + ("setl ~" (dest nasm-x86-register-lsb-alias)) + ("and ~, 1" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op less-than) (,const-or-reg? op-a) (,const-or-reg? op-b))) + (rewrite-rule ("cmp ~, ~" (op-a const-or-reg) (op-b const-or-reg)) + ("setl ~" (dest nasm-x86-register-lsb-alias)) + ("and ~, 1" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op equal-to) (,register? op-a) (const (,intconst? op-b)))) + (rewrite-rule ("cmp ~, ~" (op-a register) (op-b intconst)) + ("sete ~" (dest nasm-x86-register-lsb-alias)) + ("and ~, 1" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op equal-to) (,register? op-a) (label (,label? op-b)))) + (rewrite-rule ("cmp ~, ~" (op-a register) (op-b label)) + ("sete ~" (dest nasm-x86-register-lsb-alias)) + ("and ~, 1" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op equal-to) (,const-or-reg? op-a) (,const-or-reg? op-b))) + (rewrite-rule ("cmp ~, ~" (op-a const-or-reg) (op-b const-or-reg)) + ("sete ~" (dest nasm-x86-register-lsb-alias)) + ("and ~, 1" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op less-than-or-equal) (,register? op-a) (const (,intconst? op-b)))) + (rewrite-rule ("cmp ~, ~" (op-a register) (op-b intconst)) + ("setle ~" (dest nasm-x86-register-lsb-alias)) + ("and ~, 1" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op less-than-or-equal) (,register? op-a) (,register? op-b))) + (rewrite-rule ("cmp ~, ~" (op-a register) (op-b register)) + ("setle ~" (dest nasm-x86-register-lsb-alias)) + ("and ~, 1" (dest register)))) + + )) + diff --git a/src/sasm/nasmx86/control.scm b/src/sasm/nasmx86/control.scm new file mode 100644 index 0000000..fde7083 --- /dev/null +++ b/src/sasm/nasmx86/control.scm @@ -0,0 +1,66 @@ +(need sasm/machdesc) + +(define (nasm-x86-control-simple) + (machine-description + ;; simple control flow ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(goto (label (,label? label)))) + (rewrite-rule "jmp NEAR ~" (label label))) + + (instruction (input-pattern `(goto (,const-or-reg? dest))) + (rewrite-rule "jmp ~" (dest const-or-reg))) + + (instruction (input-pattern `(branch-true (label (,label? label)))) + (rewrite-rule "jnz NEAR ~" (label label))) + + (instruction (input-pattern `(branch-false (label (,label? label)))) + (rewrite-rule "jz NEAR ~" (label label))) + + (instruction (input-pattern `(branch-nonzero (label (,label? label)) + (,register? reg))) + (rewrite-rule ("cmp ~, 0" (reg register)) + ("jnz NEAR ~" (label label)) + )) + + (instruction (input-pattern `(branch-zero (label (,label? label)) + (,register? reg))) + (rewrite-rule ("cmp ~, 0" (reg register)) + ("jz NEAR ~" (label label)) + )) + )) + +(define (nasm-x86-control-complex) + (machine-description + (instruction (input-pattern `(branch-nonzero (label (,label? label)) + (result (op greater-than) + (,register? reg) + (const (,intconst? op-b))))) + (rewrite-rule ("cmp ~, ~" (reg register) (op-b intconst)) + ("jg NEAR ~" (label label)))) + + (instruction (input-pattern `(branch-nonzero (label (,label? label)) + (result (op equal-to) + (,register? reg) + (const (,intconst? op-b))))) + (rewrite-rule ("cmp ~, ~" (reg register) (op-b intconst)) + ("je NEAR ~" (label label)))) + + (instruction (input-pattern `(branch-nonzero (label (,label? label)) + (result (op greater-than) + (,register? reg-a) + (,register? reg-b)))) + (rewrite-rule ("cmp ~, ~" (reg-a register) (reg-b register)) + ("jg NEAR ~" (label label)))) + + (instruction (input-pattern `(branch-nonzero (label (,label? label)) + (result (op less-than-or-equal) + (,register? reg) + (const (,intconst? op-b))))) + (rewrite-rule ("cmp ~, ~" (reg register) (op-b intconst)) + ("jle NEAR ~" (label label)))) + + )) + +(define (nasm-x86-control) + (append (nasm-x86-control-complex) + (nasm-x86-control-simple))) diff --git a/src/sasm/nasmx86/data.scm b/src/sasm/nasmx86/data.scm new file mode 100644 index 0000000..1108553 --- /dev/null +++ b/src/sasm/nasmx86/data.scm @@ -0,0 +1,19 @@ +(need sasm/machdesc) + +(define (nasm-x86-data) + (machine-description + ;; data declaration ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; directive + (instruction (input-pattern `(data (const (,intconst? i)))) + (rewrite-rule "dd ~" (i intconst))) + +;; directive + (instruction (input-pattern `(data (label (,label? l)))) + (rewrite-rule "dd ~" (l label))) + + (instruction (input-pattern `(data (const (,string? str)))) + (rewrite-rule "db ~" (str nasm-string))) + + )) + diff --git a/src/sasm/nasmx86/debug.scm b/src/sasm/nasmx86/debug.scm new file mode 100644 index 0000000..ce7ae09 --- /dev/null +++ b/src/sasm/nasmx86/debug.scm @@ -0,0 +1,8 @@ +(need sasm/machdesc) + +(define (nasm-x86-debug) + (machine-description + (instruction (input-pattern `(perform (op break))) + (rewrite-rule "int 3")) + )) + diff --git a/src/sasm/nasmx86/interp.scm b/src/sasm/nasmx86/interp.scm new file mode 100644 index 0000000..9fa9a14 --- /dev/null +++ b/src/sasm/nasmx86/interp.scm @@ -0,0 +1,40 @@ +(need sasm/machdesc) + +(define (nasm-x86-interp-support) + (machine-description + ;; interpreter support ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(test (op interp-gc-not-a-number) (,register? reg))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-NOT-A-NUMBER ~" + (reg register))) + + (instruction (input-pattern `(test (op interp-gc-test-symbolic-pointer) (,register? reg))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-TEST-SYMBOLIC-POINTER ~" + (reg register))) + + (instruction (input-pattern `(assign (,register? dest) (op interp-gc-memory-area-size) (,register? reg))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-MEMORY-AREA-SIZE ~ ~" + (dest register) + (reg register))) + + (instruction (input-pattern `(assign (,register? dest) (op interp-gc-memory-ref) (,register? address) (,register? index))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-MEMORY-REF ~ ~ ~" + (dest register) + (address register) + (index register))) + + (instruction (input-pattern `(assign (,register? dest) (op interp-gc-auxiliary-stack))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-AUXILIARY-STACK ~" + (dest register))) + + (instruction (input-pattern `(assign (,register? dest) (op interp-gc-global-addrs))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-GLOBAL-ADDRS ~" + (dest register))) + + (instruction (input-pattern '(perform (op debug-break))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-DEBUG-BREAK")) + + (instruction (input-pattern `(perform (op debug-out) (,register? reg))) + (rewrite-rule "@@@ERROR-INVALID-TO-ASSEMBLE-DEBUG-OUT")) + )) + diff --git a/src/sasm/nasmx86/labels.scm b/src/sasm/nasmx86/labels.scm new file mode 100644 index 0000000..0e21e8c --- /dev/null +++ b/src/sasm/nasmx86/labels.scm @@ -0,0 +1,12 @@ +(need sasm/machdesc) + +(define (nasm-x86-machine-labels) + (machine-description + ;; labels ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ;; directive + (instruction (input-pattern `(label (,label? label))) + (rewrite-rule "~:" (label label))) + + )) + diff --git a/src/sasm/nasmx86/load-array.scm b/src/sasm/nasmx86/load-array.scm new file mode 100644 index 0000000..4bb4836 --- /dev/null +++ b/src/sasm/nasmx86/load-array.scm @@ -0,0 +1,37 @@ +(need sasm/machdesc) + +(define (nasm-x86-load-array) + (machine-description + ;; load-array ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(assign (,register? dest) (op load-array) (const (,label? array)) (const (,intconst? offset)))) + (rewrite-rule "mov ~, [~~~]" + (dest register) + (array label) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset))) + + (instruction (input-pattern `(assign (,register? dest) (op load-array) (label (,label? array)) (const (,intconst? offset)))) + (rewrite-rule "mov ~, [~~~]" + (dest register) + (array label) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset))) + + (instruction (input-pattern `(assign (,register? dest) (op load-array) (,register? array) (const (,intconst? offset)))) + (rewrite-rule "mov ~, [~~~]" + (dest register) + (array register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset))) + + (instruction (input-pattern `(assign (,register? dest) (op load-array) (,const-or-reg? array) (,const-or-reg? index))) + (rewrite-rule "mov ~, [~~~]" + (dest register) + (array const-or-reg) + (index nasm-x86-offset+/-) + (index nasm-x86-offset))) + + )) + + diff --git a/src/sasm/nasmx86/machine.scm b/src/sasm/nasmx86/machine.scm new file mode 100644 index 0000000..6ddb994 --- /dev/null +++ b/src/sasm/nasmx86/machine.scm @@ -0,0 +1,8 @@ +(define (nasm-x86-machine) + (append (nasm-x86-machine-base) + (nasm-x86-standard-twoarg-binop 'add "add") + (nasm-x86-standard-twoarg-binop 'sub "sub") + (nasm-x86-standard-twoarg-binop 'bit-xor "xor") + (nasm-x86-standard-twoarg-binop 'bit-or "or") + (nasm-x86-standard-twoarg-binop 'bit-and "and"))) + diff --git a/src/sasm/nasmx86/mul.scm b/src/sasm/nasmx86/mul.scm new file mode 100644 index 0000000..29675b9 --- /dev/null +++ b/src/sasm/nasmx86/mul.scm @@ -0,0 +1,56 @@ +(need sasm/machdesc) + +(define (nasm-x86-multiply) + (machine-description + ;; multiply - binop w/ register constraints + + (instruction (input-pattern `(assign (,x86-accumulator? dest) + (op hyg-mul) + (,x86-accumulator? dest) + (result (op load-array) + (,register? ptr) + (const (,integer? offset))))) + (rewrite-rule ("imul dword [~~~]" + (ptr register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset)))) + + (instruction (input-pattern `(assign (,x86-accumulator? dest) (op hyg-mul) (,x86-accumulator? dest) (,register? operand))) + (rewrite-rule ("imul ~" (operand register)))) + + (instruction (input-pattern `(assign (,register? dest) + (op mul) + (,register? op-a) + (result (op load-array) + (,register? ptr) + (const (,integer? offset))))) + (rewrite-rule ((assign (reg eax) (replace op-a)) (op-a sym-register)) + ("imul dword [~~~]" + (ptr register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset)) + ((assign (replace dest) (reg eax)) (dest sym-register))) + (side-effects (reg eax) (reg edx)) + (insel-rewrite-rule (assign (reg accum) (replace op-a)) + (assign (reg accum) (op hyg-mul) (reg accum) + (result (op load-array) + (replace ptr) + (const (replace offset)))) + (assign (replace dest) (reg accum)) )) + + (instruction (input-pattern `(assign (,register? dest) (op mul) (,const-or-reg? op-a) (,const-or-reg? op-b))) + (rewrite-rule ((assign (reg eax) (replace op-a)) (op-a sym-register)) + ("imul ~" (op-b register)) + ((assign (replace dest) (reg eax)) (dest sym-register))) + (side-effects (reg eax) (reg edx)) + (insel-rewrite-rule (assign (replace-temp x) (replace op-b)) + (assign (reg accum) (replace op-a)) + (assign (reg accum) (op hyg-mul) (reg accum) (replace-temp x)) + (assign (replace dest) (reg accum)) )) + + (instruction (input-pattern `(assign (,register? dest) (op bit-not) (,const-or-reg? src))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-const-or-reg)) + ("not ~" (dest register)))) + + )) + diff --git a/src/sasm/nasmx86/preamble.scm b/src/sasm/nasmx86/preamble.scm new file mode 100644 index 0000000..828a270 --- /dev/null +++ b/src/sasm/nasmx86/preamble.scm @@ -0,0 +1,31 @@ +(need sasm/machdesc) + +(define (nasm-x86-preamble) + (machine-description + ;; preamble ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; directive + (instruction (input-pattern `(global-preamble)) + (rewrite-rule ("bits 32") + ("section .text") + (""))) + + (instruction (input-pattern `(data-preamble)) + (rewrite-rule ("") + ("section .data") + (""))) + + (instruction (input-pattern `(export (,label? label))) + (rewrite-rule "global ~" (label label))) + + (instruction (input-pattern `(extern (,label? label))) + (rewrite-rule "extern ~" (label label))) + + (instruction (input-pattern `(perform (op reserve-locals) (const (,intconst? n)))) + (rewrite-rule "sub esp, ~" + (n (lambda (x) (* 4 x))))) + + (instruction (input-pattern `(perform (op function-preamble))) + (rewrite-rule)) + )) + diff --git a/src/sasm/nasmx86/return.scm b/src/sasm/nasmx86/return.scm new file mode 100644 index 0000000..63b7a72 --- /dev/null +++ b/src/sasm/nasmx86/return.scm @@ -0,0 +1,32 @@ +(need sasm/machdesc) + +(define (nasm-x86-return) + (machine-description + ;; return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; primary + (instruction (input-pattern `(return)) + (rewrite-rule ("ret"))) + + (instruction (input-pattern `(return (const (,intconst? val)))) + (rewrite-rule ("ret ~" (val (lambda (x) (* 4 x)))))) + + ;; assignment expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(assign (,register? dest) (const (,(lambda (x) (or (label? x) (number? x))) c)))) + (rewrite-rule "mov ~, ~" + (dest register) + (c (lambda (x) (cond ((label? x) (label x)) ((number? x) x) (else (error "bad constant"))))))) + + (instruction (input-pattern `(assign (,register? dest) (label (,label? label)))) + (rewrite-rule "mov ~, ~" + (dest register) + (label label))) + + (instruction (input-pattern `(assign (,register? dest) (,const-or-reg? src))) + (rewrite-rule "mov ~, ~" + (dest register) + (src const-or-reg))) + + )) + diff --git a/src/sasm/nasmx86/shift.scm b/src/sasm/nasmx86/shift.scm new file mode 100644 index 0000000..3cc4e32 --- /dev/null +++ b/src/sasm/nasmx86/shift.scm @@ -0,0 +1,46 @@ +(need sasm/machdesc) + +(define (nasm-x86-rshift) + (machine-description + ;; bit-shift operations, variable offset + + ;; bit-arith-rshift + + (instruction (input-pattern `(assign (,register? dest) (op hyg-bit-lshift) (,register? src) (,register? bits))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ((assign (reg ecx) (replace bits)) (bits sym-register)) + ("sal ~, cl" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op bit-lshift) (,const-or-reg? src) (,const-or-reg? bits))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-const-or-reg)) + ((assign (reg ecx) (replace bits)) (bits sym-const-or-reg)) + ("sal ~, cl" (dest register))) + (side-effects (reg ecx)) + (insel-rewrite-rule (assign (replace dest) (op hyg-bit-lshift) (replace src) (replace bits)))) + + (instruction (input-pattern `(assign (,register? dest) (op hyg-bit-rshift) (,register? src) (,register? bits))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ((assign (reg ecx) (replace bits)) (bits sym-register)) + ("shr ~, cl" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op bit-rshift) (,register? src) (,register? bits))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ((assign (reg ecx) (replace bits)) (bits sym-register)) + ("shr ~, cl" (dest register))) + (side-effects (reg ecx)) + (insel-rewrite-rule (assign (replace dest) (op hyg-bit-rshift) (replace src) (replace bits)))) + + (instruction (input-pattern `(assign (,register? dest) (op hyg-bit-arith-rshift) (,register? src) (,register? bits))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ((assign (reg ecx) (replace bits)) (bits sym-register)) + ("sar ~, cl" (dest register)))) + + (instruction (input-pattern `(assign (,register? dest) (op bit-arith-rshift) (,register? src) (,register? bits))) + (rewrite-rule ((assign (replace dest) (replace src)) (dest sym-register) (src sym-register)) + ((assign (reg ecx) (replace bits)) (bits sym-register)) + ("sar ~, cl" (dest register))) + (side-effects (reg ecx)) + (insel-rewrite-rule (assign (replace dest) (op hyg-bit-arith-rshift) (replace src) (replace bits)))) + + )) + diff --git a/src/sasm/nasmx86/stack.scm b/src/sasm/nasmx86/stack.scm new file mode 100644 index 0000000..185ce16 --- /dev/null +++ b/src/sasm/nasmx86/stack.scm @@ -0,0 +1,29 @@ +(need sasm/machdesc) + +(define (nasm-x86-stack) + (machine-description + ;; push & pop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(push (const (,intconst? arg)))) + (rewrite-rule "push dword ~" + (arg intconst))) + + (instruction (input-pattern `(push (result (op load-array) (,register? ptr) (const (,intconst? offset))))) + (rewrite-rule "push dword [~~~]" + (ptr register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset))) + + (instruction (input-pattern `(push (,register? arg))) + (rewrite-rule "push ~" + (arg register))) + + (instruction (input-pattern `(pop (const (,number? n)))) + (rewrite-rule "add esp, ~" + (n (lambda (x) (* x 4))))) + + (instruction (input-pattern `(pop (,register? dest))) + (rewrite-rule "pop dword ~" (dest register))) + + )) + diff --git a/src/sasm/nasmx86/store-array.scm b/src/sasm/nasmx86/store-array.scm new file mode 100644 index 0000000..d6c1d3b --- /dev/null +++ b/src/sasm/nasmx86/store-array.scm @@ -0,0 +1,71 @@ +(need sasm/machdesc) + +(define (nasm-x86-store-array) + (machine-description + ;; store-array ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (instruction (input-pattern `(perform (op store-array) (const (,label? array)) (const (,intconst? offset)) (const (,intconst? value)))) + (rewrite-rule "mov dword [~~~], ~" + (array label) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value intconst))) + + (instruction (input-pattern `(perform (op store-array) (const (,label? array)) (const (,intconst? offset)) (,register? value))) + (rewrite-rule "mov dword [~~~], ~" + (array label) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value register))) + + (instruction (input-pattern `(perform (op store-array) (label (,label? array)) (const (,intconst? offset)) (,register? value))) + (rewrite-rule "mov dword [~~~], ~" + (array label) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value register))) + + (instruction (input-pattern `(perform (op store-array) (,register? array) (const (,intconst? offset)) (,register? value))) + (rewrite-rule "mov [~~~], ~" + (array register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value register))) + + (instruction (input-pattern `(perform (op store-array) (,register? array) (const (,intconst? offset)) (const (,intconst? value)))) + (rewrite-rule "mov dword [~~~], ~" + (array register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value intconst))) + + (instruction (input-pattern `(perform (op store-array) (,register? pointer) (,register? offset) (const (,intconst? value)))) + (rewrite-rule "mov dword [~~~], ~" + (pointer register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value intconst))) + + (instruction (input-pattern `(perform (op store-array) (,register? pointer) (const (,intconst? offset)) (label (,label? value)))) + (rewrite-rule "mov dword [~~~], ~" + (pointer register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value label))) + + (instruction (input-pattern `(perform (op store-array) (,register? pointer) (,register? offset) (label (,label? value)))) + (rewrite-rule "mov dword [~~~], ~" + (pointer register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value label))) + + (instruction (input-pattern `(perform (op store-array) (,register? pointer) (,register? offset) (,register? value))) + (rewrite-rule "mov [~~~], ~" + (pointer register) + (offset nasm-x86-offset+/-) + (offset nasm-x86-offset) + (value register))) + + )) + diff --git a/src/sasm/nasmx86/util.scm b/src/sasm/nasmx86/util.scm new file mode 100644 index 0000000..c998944 --- /dev/null +++ b/src/sasm/nasmx86/util.scm @@ -0,0 +1,46 @@ +(define nasm-x86-registers + '((accum . "eax") (operand . "ebx") (this . "ecx") (index . "edx") + (link . "edi") (pointer . "esi"))) + +(define nasm-x86-sys-registers + '((frame-pointer . "ebp") (stack-pointer . "esp"))) + +(define (nasm-x86-register-lsb-alias reg) + (case (string->symbol (register reg)) + ((eax) "al") + ((ebx) "bl") + ((ecx) "cl") + ((edx) "dl") + (else (error "Invalid x86 register -- NASM-X86-REGISTER-LSB-ALIAS" reg)))) + +(define (nasm-x86-offset+/- x) + (cond ((symbol? x) "+") + ((register? x) "+") + ((negative? x) "-") + ((positive? x) "+") + ((zero? x) "") + (else (error "invalid offset -- nasm-x86-offset+/-" x)))) + +(define (nasm-x86-offset x) + (cond ((symbol? x) (format "4*~" x)) + ((register? x) (format "4*~" (register x))) + ((zero? x) "") + ((number? x) (* 4 (abs x))) + (else (error "invalid offset -- nasm-x86-offset" x)))) + +(define (nasm-string s) + (string-append + "'" + (escape-string (lambda (c) + (case c + ((#\\) '(#\\ #\\)) + ((#\newline) '(#\\ #\n)) + ((#\') '(#\\ #\')) + (else (list c)))) + s) + "',0")) + +(define (x86-accumulator? x) + (or (equal? x '(reg accum)) + (equal? x '(reg eax)))) + diff --git a/src/sasm/parse/constant-operand.scm b/src/sasm/parse/constant-operand.scm new file mode 100644 index 0000000..3010710 --- /dev/null +++ b/src/sasm/parse/constant-operand.scm @@ -0,0 +1,29 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-constant-operand expression) + (sasm-parse-by-case + expression + + (sasm-syntax-case + :pattern (const (,integer? constant-integer)) + :rewrite (constant-integer) + (sasm-ast-node + (:integer-value constant-integer))) + + (sasm-syntax-case + :pattern (const (,symbol? label)) + :rewrite (label) + (sasm-ast-node + (:label-value label) + (:referenced-symbol label) + (:resolved-symbol #f))) + + (sasm-syntax-case + :pattern (const (,string? constant-string)) + :rewrite (constant-string) + (sasm-ast-node + (:string-value constant-string))) + + )) + diff --git a/src/sasm/parse/data-entry.scm b/src/sasm/parse/data-entry.scm new file mode 100644 index 0000000..a9c604d --- /dev/null +++ b/src/sasm/parse/data-entry.scm @@ -0,0 +1,40 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-global-data-entry expression) + (sasm-parse-by-case + expression + + (sasm-syntax-case + :pattern (label (,symbol? symbol)) + :rewrite (symbol) + (sasm-ast-node + (:referenced-symbol symbol) + (:resolved-symbol #f))) + + (sasm-syntax-case + :pattern (const (,integer? integer-value)) + :rewrite (integer-value) + (sasm-ast-node + (:integer-value integer-value))) + + (sasm-syntax-case + :pattern (const (,string? string-value)) + :rewrite (string-value) + (sasm-ast-node + (:string-value string-value) + (:asciiz-tag #f))) + + (sasm-syntax-case + :pattern (const :asciiz (,string? constant-string)) + :rewrite (constant-string) + (sasm-ast-node + (:string-value constant-string) + (:asciiz-tag #t))) + + + (sasm-parse-error + :error-message "Unrecognized global data entry:") + + )) + diff --git a/src/sasm/parse/extern.scm b/src/sasm/parse/extern.scm new file mode 100644 index 0000000..008eb1f --- /dev/null +++ b/src/sasm/parse/extern.scm @@ -0,0 +1,125 @@ +(need sasm/sasm-tracing) +(need sasm/sasm-ast) + +;; (define-syntax define-sasm-ast-schema2 +;; (syntax-rules (node-definition) +;; ((_ +;; (node-definition ...) ...) +;; (define +;; (let* ((known-types '( ...)) +;; (unused-1 (if *sasm-enable-debug-output* +;; (begin (display ";; ast-schema2 known-types ") +;; (display known-types)))) +;; (no-dupes (remove-duplicates eqv? known-types))) +;; (if (not (equal? known-types no-dupes)) +;; (error "Duplicate SASM AST node types defined!")) +;; (lambda (node) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; ast-schema2 invoke ") +;; (display known-types) +;; (newline) +;; (display ";; node ") +;; (display node) +;; (newline) +;; )) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; get-tag of node ") +;; (display (get-tag node)) +;; (newline))) +;; (case (get-tag node) +;; (() +;; (let ((known-attributes '( ...)) +;; (actual-attributes (map car (contents node)))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; known-attributes ") +;; (display known-attributes) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; actual-attributes ") +;; (display actual-attributes) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; subset-1 ") +;; (display (list-subset? eqv? known-attributes actual-attributes)) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; subset-2 ") +;; (display (list-subset? eqv? actual-attributes known-attributes)) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; len ") +;; (display (length actual-attributes)) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; remove-dupes-1 ") +;; (display (remove-duplicates eqv? known-attributes)) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; remove-dupes-2 ") +;; (display (remove-duplicates eqv? actual-attributes)) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; len-remove-dupes-1 ") +;; (display (length (remove-duplicates eqv? known-attributes))) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; len-remove-dupes-2 ") +;; (display (length (remove-duplicates eqv? actual-attributes))) +;; (newline))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; clause ") +;; (display (= (length actual-attributes) +;; (length (remove-duplicates eqv? known-attributes)) +;; (length (remove-duplicates eqv? actual-attributes)))) +;; (newline))) +;; (or (and (list-subset? eqv? known-attributes actual-attributes) +;; (list-subset? eqv? actual-attributes known-attributes) +;; (= (length actual-attributes) +;; (length (remove-duplicates eqv? known-attributes)) +;; (length (remove-duplicates eqv? actual-attributes)))) +;; (error "SASM AST schema violation " +;; (get-tag node) +;; known-attributes +;; actual-attributes)))) +;; ... +;; (else +;; (error "Unknown AST node type" (get-tag node)))))))))) + +;; (define-sasm-ast-schema2 sasm-ast-schema2 + +;; (node-definition +;; :defined-symbol +;; :qualified-symbol +;; :resolved-references +;; :extern-symbol) + +;; ) + + +;; (define-syntax sasm-ast-node2 +;; (syntax-rules () +;; ((_ (:name value) ...) +;; (let ((attribs (list (cons ':name value) ...))) +;; (if *sasm-enable-debug-output* +;; (begin (display ";; attribs ") +;; (display attribs) +;; (newline))) +;; (let ((node (tag ' attribs))) +;; (if *sasm-enable-debug-output* +;; (begin (display " node2 ") +;; (display node) +;; (newline) +;; (sasm-ast-schema2 node) +;; (display " after sasm-ast-schema") +;; (newline))) +;; node))))) + +(define (cons-sasm-extern extern-symbol) + (debug sasm-parse-extern-symbol extern-symbol) + (let ((ast-node (sasm-ast-node + (:defined-symbol extern-symbol) + (:qualified-symbol #f) + (:resolved-references '()) + (:extern-symbol extern-symbol)))) + (debug sasm-parse-extern-symbol-ast " " ast-node) + ast-node)) diff --git a/src/sasm/parse/instruction.scm b/src/sasm/parse/instruction.scm new file mode 100644 index 0000000..0b02bc2 --- /dev/null +++ b/src/sasm/parse/instruction.scm @@ -0,0 +1,163 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-instruction instruction) + (sasm-parse-by-case + instruction + + (sasm-syntax-case + :pattern (perform . (?? ,sasm-parse-operation operation)) + :rewrite (operation) + (sasm-ast-node + (:operation operation))) + + (sasm-syntax-case + :pattern (assign (?? ,sasm-parse-lvalue-operand destination) + (?? ,sasm-parse-operand operand)) + :rewrite (destination operand) + (sasm-ast-node + (:destination destination) + (:operand operand))) + + (sasm-syntax-case + :pattern (assign (?? ,sasm-parse-lvalue-operand destination) + . + (?? ,sasm-parse-operation operation)) + :rewrite (destination operation) + (sasm-ast-node + (:destination destination) + (:operation operation))) + + (sasm-syntax-case + :pattern (test . (?? ,sasm-parse-operation operation)) + :rewrite (operation) + (sasm-ast-node + (:operation operation))) + + (sasm-syntax-case + :pattern (branch (label (,symbol? label-name))) + :rewrite (label-name) + (sasm-ast-node + (:label-operand (sasm-ast-node + (:label-value label-name) + (:referenced-symbol label-name) + (:resolved-symbol #f))) + (:condition #t))) + + (sasm-syntax-case + :pattern (branch-true (label (,symbol? label-name))) + :rewrite (label-name) + (sasm-ast-node + (:label-operand (sasm-ast-node + (:label-value label-name) + (:referenced-symbol label-name) + (:resolved-symbol #f))) + (:condition #t))) + + (sasm-syntax-case + :pattern (branch-false (label (,symbol? label-name))) + :rewrite (label-name) + (sasm-ast-node + (:label-operand (sasm-ast-node + (:label-value label-name) + (:referenced-symbol label-name) + (:resolved-symbol #f))) + (:condition #f))) + + (sasm-syntax-case + :pattern (branch-zero (label (,symbol? label-name)) + (?? ,sasm-parse-operand operand)) + :rewrite (label-name operand) + (sasm-ast-node + (:label-operand (sasm-ast-node + (:label-value label-name) + (:referenced-symbol label-name) + (:resolved-symbol #f))) + (:condition #f) + (:operand operand))) + + (sasm-syntax-case + :pattern (branch-nonzero (label (,symbol? label-name)) + (?? ,sasm-parse-operand operand)) + :rewrite (label-name operand) + (sasm-ast-node + (:label-operand (sasm-ast-node + (:label-value label-name) + (:referenced-symbol label-name) + (:resolved-symbol #f))) + (:condition #t) + (:operand operand))) + + (sasm-syntax-case + :pattern (goto (label (,symbol? label-name))) + :rewrite (label-name) + (sasm-ast-node + (:label-operand (sasm-ast-node + (:label-value label-name) + (:referenced-symbol label-name) + (:resolved-symbol #f))) + )) + + (sasm-syntax-case + :pattern (goto (reg (,symbol? register-name))) + :rewrite (register-name) + (sasm-ast-node + (:register-operand (sasm-ast-node + (:register-name register-name))))) + + (sasm-syntax-case + :pattern (save (?? ,sasm-parse-register-operand register)) + :rewrite (register) + (sasm-ast-node + (:register-operand register))) + + (sasm-syntax-case + :pattern (restore (?? ,sasm-parse-register-operand register)) + :rewrite (register) + (sasm-ast-node + (:register-operand register))) + + (sasm-syntax-case + :pattern (push (?? ,sasm-parse-operand operand)) + :rewrite (operand) + (sasm-ast-node + (:operand operand))) + + (sasm-syntax-case + :pattern (pop (const (,integer? count))) + :rewrite (count) + (sasm-ast-node + (:element-count count))) + + (sasm-syntax-case + :pattern (pop (?? ,sasm-parse-lvalue-operand destination)) + :rewrite (destination) + (sasm-ast-node + (:destination destination))) + + (sasm-syntax-case + :pattern (return) + :rewrite () + (sasm-ast-node + (:return-instruction #t))) + + (sasm-syntax-case + :pattern (return (const (,integer? count))) + :rewrite (count) + (sasm-ast-node + (:element-count count))) + + (sasm-syntax-case + :pattern (label (,symbol? label-name)) + :rewrite (label-name) + (sasm-ast-node + (:defined-symbol label-name) + (:qualified-symbol #f) + (:label-name label-name) + (:resolved-references '()))) + + (sasm-parse-error + :error-message "Invalid instruction") + + )) + diff --git a/src/sasm/parse/lvalue-operand.scm b/src/sasm/parse/lvalue-operand.scm new file mode 100644 index 0000000..0b61080 --- /dev/null +++ b/src/sasm/parse/lvalue-operand.scm @@ -0,0 +1,39 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-lvalue-operand expression) + (sasm-parse-by-case + expression + + (sasm-syntax-case + :pattern (?? ,sasm-parse-register-operand register) + :rewrite (register) + register) + + (sasm-syntax-case + :pattern (temp (,integer? temp-number)) + :rewrite (temp-number) + (sasm-ast-node + (:temporary-number temp-number))) + + (sasm-syntax-case + :pattern (temp (,symbol? temp-name)) + :rewrite (temp-name) + (sasm-ast-node + (:temporary-name temp-name))) + + (sasm-syntax-case + :pattern (arg (,integer? argument-number)) + :rewrite (argument-number) + (sasm-ast-node + (:argument-number argument-number))) + + (sasm-syntax-case + :pattern (local (,integer? local-number)) + :rewrite (local-number) + (sasm-ast-node + (:local-number local-number))) + + )) + + diff --git a/src/sasm/parse/member.scm b/src/sasm/parse/member.scm new file mode 100644 index 0000000..e136635 --- /dev/null +++ b/src/sasm/parse/member.scm @@ -0,0 +1,19 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-class-member-function expression) + (sasm-parse-by-case + expression + + (sasm-syntax-case + :pattern (label (,symbol? symbol)) + :rewrite (symbol) + (sasm-ast-node + (:referenced-symbol symbol) + (:resolved-symbol #f))) + + (sasm-parse-error + :error-message "Unrecognized class member function declaration:") + + )) + diff --git a/src/sasm/parse/operand.scm b/src/sasm/parse/operand.scm new file mode 100644 index 0000000..089949e --- /dev/null +++ b/src/sasm/parse/operand.scm @@ -0,0 +1,41 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-operand expression) + (sasm-parse-by-case + expression + + (sasm-syntax-case + :pattern (?? ,sasm-parse-lvalue-operand operand) + :rewrite (operand) + operand) + + (sasm-syntax-case + :pattern (?? ,sasm-parse-constant-operand constant) + :rewrite (constant) + constant) + + (sasm-syntax-case + :pattern (label (,symbol? symbol-name)) + :rewrite (symbol-name) + (sasm-ast-node + (:label-value symbol-name) + (:referenced-symbol symbol-name) + (:resolved-symbol #f))) + + (sasm-syntax-case + :pattern (result . (?? ,sasm-parse-operation operation)) + :rewrite (operation) + (sasm-ast-node + (:operation operation))) + + (sasm-syntax-case + :pattern (symconst (,symbol? symconst-name)) + :rewrite (symconst-name) + (sasm-ast-node + (:symconst-name symconst-name) + (:referenced-symconst-symbol symconst-name) + (:resolved-symconst #f))) + + )) + diff --git a/src/sasm/parse/operation.scm b/src/sasm/parse/operation.scm new file mode 100644 index 0000000..5ba3c4e --- /dev/null +++ b/src/sasm/parse/operation.scm @@ -0,0 +1,18 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-operation operation) + (sasm-parse-by-case + operation + + (sasm-syntax-case + :pattern ((op (,symbol? operation-symbol)) + . + (@@ ,sasm-parse-operand operands)) + :rewrite (operation-symbol operands) + (sasm-ast-node + (:operation-name operation-symbol) + (:operands operands))) + + )) + diff --git a/src/sasm/parse/program.scm b/src/sasm/parse/program.scm new file mode 100644 index 0000000..8389ad3 --- /dev/null +++ b/src/sasm/parse/program.scm @@ -0,0 +1,15 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-program program) + (sasm-parse-by-case + program + + (sasm-syntax-case + :pattern (@@ ,sasm-parse-statement statements) + :rewrite (statements) + (sasm-ast-node + (:statements statements))) + + )) + diff --git a/src/sasm/parse/register-operand.scm b/src/sasm/parse/register-operand.scm new file mode 100644 index 0000000..fef990d --- /dev/null +++ b/src/sasm/parse/register-operand.scm @@ -0,0 +1,33 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-register-operand expression) + (sasm-parse-by-case + expression + + (sasm-syntax-case + :pattern (reg (,symbol? register-name)) + :rewrite (register-name) + (sasm-ast-node + (:register-name register-name))) + + (sasm-syntax-case + :pattern (sys frame-pointer) + :rewrite () + (sasm-ast-node + (:register-name 'frame-pointer))) + + (sasm-syntax-case + :pattern (sys stack-pointer) + :rewrite () + (sasm-ast-node + (:register-name 'stack-pointer))) + + (sasm-syntax-case + :pattern (sys (,symbol? register-name)) + :rewrite (register-name) + (sasm-ast-node + (:register-name register-name))) + + )) + diff --git a/src/sasm/parse/statement.scm b/src/sasm/parse/statement.scm new file mode 100644 index 0000000..774d0e5 --- /dev/null +++ b/src/sasm/parse/statement.scm @@ -0,0 +1,93 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) +(need sasm/sasm-tracing) +(need sasm/parse/extern) + +(define (sasm-parse-statement statement) + (sasm-parse-by-case + statement + + (sasm-syntax-case + :pattern (class (,symbol? class-symbol) + (const (,integer? class-data-size)) + . + (@@ ,sasm-parse-class-member-function + member-functions)) + :rewrite (class-symbol class-data-size member-functions) + (sasm-ast-node + (:defined-symbol class-symbol) + (:qualified-symbol #f) + (:resolved-references '()) + (:size class-data-size) + (:member-functions member-functions))) + + (sasm-syntax-case + :pattern (global (,symbol? global-symbol) + . + (@@ ,sasm-parse-global-data-entry + global-data-entries)) + :rewrite (global-symbol global-data-entries) + (sasm-ast-node + (:defined-symbol global-symbol) + (:qualified-symbol #f) + (:resolved-references '()) + (:global-data-symbol global-symbol) + (:global-data global-data-entries))) + + (sasm-syntax-case + :pattern (entry (,symbol? entry-symbol)) + :rewrite (entry-symbol) + (sasm-ast-node + (:referenced-symbol entry-symbol) + (:resolved-symbol #f) + (:entry-point-symbol entry-symbol))) + + (sasm-syntax-case + :pattern (define-symconst . (@@ ,sasm-parse-symconst-entry + symconst-entries)) + :rewrite (symconst-entries) + (sasm-ast-node + (:symconst-entries symconst-entries))) + + (sasm-syntax-case + :pattern (class-info . (? class-info-body)) + :rewrite (class-info-body) + (sasm-ast-node + (:class-info-body class-info-body))) + + (sasm-syntax-case + :pattern (extern (,symbol? extern-symbol)) + :rewrite (extern-symbol) + (cons-sasm-extern extern-symbol)) + + (sasm-syntax-case + :pattern (export (,symbol? export-symbol)) + :rewrite (export-symbol) + (sasm-ast-node + (:referenced-symbol export-symbol) + (:resolved-symbol #f))) + + (sasm-syntax-case + :pattern (include (,string? include-path)) + :rewrite (include-path) + (sasm-ast-node + (:include-path include-path))) + + (sasm-syntax-case + :pattern (function (name (,symbol? function-symbol)) + (locals (,integer? local-count)) + (body . (@@ ,sasm-parse-instruction + instructions))) + :rewrite (function-symbol local-count instructions) + (sasm-ast-node + (:defined-symbol function-symbol) + (:qualified-symbol #f) + (:resolved-references '()) + (:function-symbol function-symbol) + (:local-count local-count) + (:instructions instructions))) + + (sasm-parse-error + :error-message "Invalid statement:") + + )) diff --git a/src/sasm/parse/symconst-entry.scm b/src/sasm/parse/symconst-entry.scm new file mode 100644 index 0000000..a7adbe2 --- /dev/null +++ b/src/sasm/parse/symconst-entry.scm @@ -0,0 +1,20 @@ +(need sasm/parse/syntax) +(need sasm/sasm-ast) + +(define (sasm-parse-symconst-entry expression) + (sasm-parse-by-case + expression + + (sasm-syntax-case + :pattern ((,symbol? symconst-symbol) (,integer? symconst-value)) + :rewrite (symconst-symbol symconst-value) + (sasm-ast-node + (:defined-symconst-symbol symconst-symbol) + (:symconst-symbol symconst-symbol) + (:symconst-value symconst-value))) + + (sasm-parse-error + :error-message "Unrecognized symconst entry:") + + )) + diff --git a/src/sasm/parse/syntax.scm b/src/sasm/parse/syntax.scm new file mode 100644 index 0000000..0b1588f --- /dev/null +++ b/src/sasm/parse/syntax.scm @@ -0,0 +1,33 @@ +(need sasm/sasm-tracing) + +(define-syntax sasm-syntax-case + (syntax-rules (:pattern :rewrite) + ((_ :pattern pattern + :rewrite (symbol ...) body1 body2 ...) + (lambda (expression) + (let ((match (pattern-match (quasiquote pattern) + expression))) + (and match + (apply (lambda (symbol ...) + body1 body2 ...) + (let ((map-result (map (lambda (sym) + (let ((entry (assoc sym match))) + (if entry + (cdr entry) + (error "Unmatched variable in sasm-syntax-case" sym)))) + '(symbol ...)))) + map-result)) + )))))) + +(define-syntax sasm-parse-error + (syntax-rules (:error-message) + ((_ :error-message ...) + (lambda (expression) + (display ) + (for-each display (list ...)) + (newline) + (write expression) + (newline) + (newline) + #f)))) + diff --git a/src/sasm/parse/util.scm b/src/sasm/parse/util.scm new file mode 100644 index 0000000..a891bd5 --- /dev/null +++ b/src/sasm/parse/util.scm @@ -0,0 +1,16 @@ +(need sasm/sasm-tracing) + +(define (sasm-parse-by-case expression . cases) + (define (iter cases) + (debug sasm-parse-by-case-iter cases) + (if (null? cases) + #f + (let* ((current (begin (debug sasm-parse-by-case-current-case (car cases)) + (car cases))) + (result ((car cases) expression))) + (debug sasm-parse-by-case-result result) + (or result + (iter (cdr cases)))))) + (debug sasm-parse-by-case expression) + (iter cases)) + diff --git a/src/sasm/sasm-analyze.scm b/src/sasm/sasm-analyze.scm new file mode 100644 index 0000000..a4f4e34 --- /dev/null +++ b/src/sasm/sasm-analyze.scm @@ -0,0 +1,247 @@ +;; sasm-analyze.scm +;; +;; A component of the SASM interpreter which analyzes SASM source, +;; performing static syntactic and semantic analysis which validates +;; the code and prepares it for efficient runtime interpretation. + +(need sasm/sasm-ast) +(need sasm/sasm-visitor) + +;; +;; == SASM ANALYSIS DESIGN NOTES == +;; +;; ==== Modules +;; +;; The SASM analyzer is capable of loading multiple SASM source +;; modules into the same analysis session in a way that simulates the +;; process of linking multiple modules when the SASM code is +;; translated to object code. +;; +;; The scoping of globally imported and exported symbols, as well as +;; module-local symbols, is of key importantance to this simulation. +;; +;; ==== Scopes +;; +;; - Program Scope; a Program contains multiple Modules. Exported +;; and imported global variables exist in Program Scope. +;; +;; - Module Scope; A Module contains multiple Functions. Symbols +;; that are declared in the module outside of the body of a function +;; are module-local unless exported. +;; +;; - Function Scope; A Function contains multiple instructions which +;; may reference labels in any of the scopes. Labels defined in a +;; function are local to the Function. +;; + +(define (sasm-program-extern-symbols program) + (let ((result '())) + (define-sasm-ast-visitor visitor + (define-case ((extern ) + (symbol :extern-symbol)) + (set! result (cons symbol result)))) + (sasm-visit-ast program visitor) + result)) + +;; Retrieves all of the symbols defined by the specified SASM program +;; abstract syntax tree. These may or may not be exported. Imported +;; symbols are not "defined". This returns top-level symbols only. +;; +(define (sasm-program-defined-symbols program) + (let ((result '())) + (define (accumulate-symbol symbol) + (if (member symbol result) + (error "Multiple definitions of symbol" symbol) + (set! result (cons symbol result)))) + + (define-sasm-ast-visitor visitor + (define-case ((class ) + (symbol :defined-symbol)) + (accumulate-symbol symbol)) + + (define-case ((global ) + (symbol :defined-symbol)) + (accumulate-symbol symbol)) + + (define-case ((function ) + (symbol :defined-symbol)) + (accumulate-symbol symbol))) + + (sasm-visit-ast program visitor) + result)) + +;; Returns a list of all unique symbols referenced in the specified +;; (and perhaps partial) abstract syntax tree. +;; +(define (sasm-program-referenced-symbols ast) + (define result '()) + (define (accumulate-symbol! symbol) + (if (not (member symbol result)) + (set! result (cons symbol result)))) + (define-sasm-ast-visitor visitor + (define-case ((operand ) + (symbol :label-value)) + (accumulate-symbol! symbol))) + (sasm-visit-ast ast visitor) + (reverse result)) + +(define (sasm-function-defined-labels function) + (let ((result + (sasm-visit-ast-with-accumulator + accumulate! + function + + (define-case ((label-object ) + (label-symbol :label-name)) + (accumulate! label))))) + (let* ((result-symbols (map (lambda (x) (sasm-ast-node-attribute x :label-name)) + result))) + (let ((no-dupes (remove-duplicates eqv? result-symbols))) + (if (not (equal? no-dupes result-symbols)) + (error "Duplicate labels defined in function " + (subtract-lists eqv? result-symbols no-dupes))) + result)))) + +(define (sasm-program-analyze-symbols! module-prefix program) + (define status #t) + (define current-scope '()) + (define scope-depth 0) + (define current-program #f) + (define current-function #f) + (define undefined-symbols '()) + + (define (symbol-error message . args) + (display "ERROR: ") + (display message) + (for-each display args) + (newline) + (set! status #f)) + + (define (look-up-symbol-in-scope symbol scope) + (and (not (null? scope)) + (let ((entry (assoc symbol (cdr scope)))) + (or entry + (look-up-symbol-in-scope symbol (car scope)))))) + + (define (look-up-symbol symbol) + (look-up-symbol-in-scope symbol current-scope)) + + (define (prefix-symbol prefix symbol . symbols) + (string->symbol (apply string-append (map (lambda (x) + (if (string? x) + x + (symbol->string x))) + (cons prefix (cons symbol symbols)))))) + + (define (push-scope! symbols) + (set! scope-depth (+ 1 scope-depth)) + (set! current-scope (cons current-scope symbols))) + + (define (pop-scope!) + (set! scope-depth (+ 1 scope-depth)) + (set! current-scope (car current-scope))) + + (define (check-duplicates context symbol-list) + (define (iter list) + (cond ((null? list) #t) + ((member (car symbol-list) (cdr symbol-list)) + (symbol-error "Duplicate symbol detected " context " " (car symbol-list))) + (else + (iter (cdr list))))) + + (iter symbol-list)) + + (define (resolve-reference! node) + (let* ((symbol (sasm-ast-node-attribute node :referenced-symbol)) + (value (look-up-symbol symbol))) + (if (not value) + (if (not (member symbol undefined-symbols)) + (begin (symbol-error "Undefined symbol [" symbol "]") + (set! undefined-symbols (cons symbol undefined-symbols)))) + (begin + (sasm-ast-node-attribute! node :resolved-symbol + (cdr value)) + (sasm-ast-node-append-attribute! (cdr value) :resolved-references + node))))) + + (define-sasm-ast-visitor visitor + + ;; + ;; Push a top-level scope when processing the main program node. + ;; + (define-case ((program )) + (:preorder + (let* ((externs (sasm-filter-ast program )) + (defined (sasm-filter-ast program + + + )) + (defined-symbols (map (sasm-ast-getter :defined-symbol) + defined)) + (extern-symbols (map (sasm-ast-getter :defined-symbol) + externs)) + (top-level (append externs defined)) + (top-level-symbols (map (sasm-ast-getter :defined-symbol) + top-level)) + (exports (sasm-filter-ast program )) + (export-symbols (map (sasm-ast-getter :referenced-symbol) exports)) + ) + (check-duplicates "" top-level-symbols) + (for-each (lambda (export) + (if (not (member export defined-symbols)) + (symbol-error "Symbol exported but not defined [" export "]"))) + export-symbols) + (for-each (lambda (node symbol) + (if (and (not (member symbol export-symbols)) + (not (member symbol extern-symbols))) + (sasm-ast-node-attribute! node :qualified-symbol + (prefix-symbol "@" + module-prefix + ":" + symbol)) + (sasm-ast-node-attribute! node :qualified-symbol symbol))) + top-level + top-level-symbols) + (set! current-program program) + (push-scope! (map cons top-level-symbols top-level)))) + (:postorder + (set! current-program #f) + (pop-scope!))) + + ;; + ;; Push a function-level scope when processing each function node. + ;; + (define-case ((function ) + (function-symbol :defined-symbol)) + (:preorder + (let* ((label-directives (sasm-filter-ast function )) + (label-symbols (map (sasm-ast-getter :defined-symbol) label-directives))) + (for-each (lambda (node symbol) + (sasm-ast-node-attribute! node :qualified-symbol + (prefix-symbol "@" + module-prefix + ":" + function-symbol + ":" + symbol))) + label-directives + label-symbols) + (check-duplicates function-symbol label-symbols) + (push-scope! (map cons label-symbols label-directives)) + (set! current-function function)) + ) + (:postorder + (set! current-function #f) + (pop-scope!))) + + (define-case ((reference + + + + )) + (resolve-reference! reference)) + + ) + + (sasm-visit-ast program visitor) + status) diff --git a/src/sasm/sasm-ast.scm b/src/sasm/sasm-ast.scm new file mode 100644 index 0000000..b3840ef --- /dev/null +++ b/src/sasm/sasm-ast.scm @@ -0,0 +1,292 @@ +;; sasm-ast.scm +;; +;; AST-building routines, syntax, etc. for the SASM language. + +(need scheme/tag) +(need util/list) + +(define (sasm-ast-node-type-check table node) + (let ((entry (assoc (get-tag node) table))) + (if (not entry) + (error "SASM AST unknown node type " + (get-tag node)) + (let ((known-attributes (cdr entry)) + (actual-attributes (map car (contents node)))) + (or (and (list-subset? eqv? known-attributes actual-attributes) + (list-subset? eqv? actual-attributes known-attributes) + (= (length actual-attributes) + (length (remove-duplicates eqv? known-attributes)) + (length (remove-duplicates eqv? actual-attributes)))) + (error "SASM AST schema violation " + (get-tag node) + known-attributes + actual-attributes)))))) + +;; (define-syntax define-sasm-ast-schema +;; (syntax-rules (node-definition) +;; ((_ +;; (node-definition ...) +;; ...) +;; (lambda (node) +;; ; (let ((table '(() ; ...) +;; ; ...))) +;; (sasm-ast-node-type-check '() node))))) + +(define-syntax define-sasm-ast-schema + (syntax-rules (node-definition) + ((_ + (node-definition ...) ...) + (define + (lambda (node) + (let ((table '(( ...) ...))) + (sasm-ast-node-type-check table node))))))) + +;; (define-syntax define-sasm-ast-schema +;; (syntax-rules (node-definition) +;; ((_ +;; (node-definition ...) ...) +;; (define +;; (let* ((known-types '( ...)) +;; (no-dupes (remove-duplicates eqv? known-types))) +;; (if (not (equal? known-types no-dupes)) +;; (error "Duplicate SASM AST node types defined!")) +;; (lambda (node) +;; (case (get-tag node) +;; (() +;; (let ((known-attributes '( ...)) +;; (actual-attributes (map car (contents node)))) +;; (or (and (list-subset? eqv? known-attributes actual-attributes) +;; (list-subset? eqv? actual-attributes known-attributes) +;; (= (length actual-attributes) +;; (length (remove-duplicates eqv? known-attributes)) +;; (length (remove-duplicates eqv? actual-attributes)))) +;; (error "SASM AST schema violation " +;; (get-tag node) +;; known-attributes +;; actual-attributes)))) +;; ... +;; (else +;; (error "Unknown AST node type" (get-tag node)))))))))) + +(define-sasm-ast-schema sasm-ast-schema + (node-definition + :statements) + + (node-definition + :referenced-symbol + :resolved-symbol) + + (node-definition + :referenced-symbol + :resolved-symbol) + + (node-definition + :integer-value) + + (node-definition + :string-value + :asciiz-tag) + + (node-definition + :defined-symconst-symbol + :symconst-symbol + :symconst-value) + + (node-definition + :register-name) + + (node-definition + :register-name) + + (node-definition + :integer-value) + + (node-definition + :label-value + :referenced-symbol + :resolved-symbol) + + (node-definition + :string-value) + + (node-definition + :temporary-number) + + (node-definition + :temporary-name) + + (node-definition + :argument-number) + + (node-definition + :local-number) + + (node-definition + :operation) + + (node-definition + :symconst-name + :referenced-symconst-symbol + :resolved-symconst) + + (node-definition + :operation-name + :operands) + + (node-definition + :operation) + + (node-definition + :destination + :operand) + + (node-definition + :destination + :operation) + + (node-definition + :operation) + + (node-definition + :label-operand + :condition) + + (node-definition + :label-operand + :condition + :operand) + + (node-definition + :label-operand) + + (node-definition + :register-operand) + + (node-definition + :register-operand) + + (node-definition + :register-operand) + + (node-definition + :operand) + + (node-definition + :element-count) + + (node-definition + :destination) + + (node-definition + :return-instruction) + + (node-definition + :element-count) + + (node-definition + :defined-symbol + :qualified-symbol + :label-name + :resolved-references) + + (node-definition + :defined-symbol + :qualified-symbol + :resolved-references + :size + :member-functions) + + (node-definition + :defined-symbol + :qualified-symbol + :resolved-references + :global-data-symbol + :global-data) + + (node-definition + :referenced-symbol + :resolved-symbol + :entry-point-symbol) + + (node-definition + :symconst-entries) + + (node-definition + :class-info-body) + + (node-definition + :defined-symbol + :qualified-symbol + :resolved-references + :extern-symbol) + + (node-definition + :referenced-symbol + :resolved-symbol) + + (node-definition + :include-path) + + (node-definition + :defined-symbol + :qualified-symbol + :resolved-references + :function-symbol + :local-count + :instructions)) + +(define-syntax sasm-ast-node + (syntax-rules () + ((_ (:name value) ...) + (let ((node (tag ' (list (cons ':name value) ...)))) + (sasm-ast-schema node) + node)))) + +(define-syntax sasm-ast-node-append-attribute! + (syntax-rules () + ((_ ) + (let* ((node ) + (current-value (sasm-ast-node-attribute node ))) + (sasm-ast-node-attribute! node + (append current-value + (list ))))))) + +(define (sasm-ast-node-get-attribute node attribute) + (let ((entry (assoc attribute (contents node)))) + (if entry + (cdr entry) + (error "sasm-ast-node-get-attribute attribute not found" attribute)))) + +(define-syntax sasm-ast-node-attribute + (syntax-rules () + ((_ node :attribute) + (let ((entry (assoc ':attribute (contents node)))) + (if entry + (cdr entry) + (error "sasm-ast-node-attribute -- attribute not found" ':attribute)))) + ((_ node :attribute) + (let ((entry (assoc ':attribute (safe-contents node ')))) + (if entry + (cdr entry) + (error "sasm-ast-node-attribute -- attribute not found" ':attribute)))))) + +(define-syntax sasm-ast-getter + (syntax-rules () + ((_ ) + (lambda (node) + (sasm-ast-node-attribute node ))))) + +(define-syntax sasm-ast-node-attribute! + (syntax-rules () + ((_ node :attribute value) + (let ((entry (assoc ':attribute (contents node)))) + (if entry + (begin (set-cdr! entry value) + value) + (error "sasm-ast-node-attribute! -- attribute not found" ':attribute)))) + ((_ node :attribute value) + (let ((entry (assoc ':attribute (safe-contents node ')))) + (if entry + (begin (set-cdr! entry value) + value) + (error "sasm-ast-node-attribute! -- attribute not found" ':attribute)))))) diff --git a/src/sasm/sasm-codegen.scm b/src/sasm/sasm-codegen.scm new file mode 100644 index 0000000..9214655 --- /dev/null +++ b/src/sasm/sasm-codegen.scm @@ -0,0 +1,45 @@ +;; sasm-codegen.scm +;; +;; This module provides routines that simplify the work of generating +;; sasm code. + +(define (sasm-pretty-print obj port) + (cond + ((and (pair? obj) + (eqv? 'function (car obj))) + (display "(function" port) + (newline port) + (for-each (lambda (part) + (if (and (pair? part) + (not (eqv? 'body (car part)))) + (begin (display " " port) + (write part port) + (newline port)))) + obj) + (let ((body (assoc 'body (cdr obj)))) + (if body + (begin (display " (body" port) + (newline port) + (for-each (lambda (insn) + (display " " port) + (write insn port) + (newline port)) + (cdr body)) + (display " ))" port) + (newline port)) + (begin + (display " )" port) + (newline port))))) + ((and (pair? obj) + (eqv? 'global (car obj))) + (display "(global " port) + (write (cadr obj) port) + (newline port) + (for-each (lambda (elem) + (display " " port) + (write elem port) + (newline port)) + (cddr obj)) + (display " )" port)) + (else + (write obj port)))) diff --git a/src/sasm/sasm-core.scm b/src/sasm/sasm-core.scm new file mode 100644 index 0000000..e522072 --- /dev/null +++ b/src/sasm/sasm-core.scm @@ -0,0 +1,200 @@ +;; sasm-core.scm +;; SASM transform routines + +(need pat/pat) +(need sasm/sasm-dataflow) +(need sasm/sasm-regalloc) +(need sasm/sasm-parse) +(need sasm/sasm-analyze) + +(define *sasm-transform-function-count* 0) +(define *sasm-output-progress* #f) + +(define (sasm-remove-directives sasm) + (filter (lambda (x) (not (equal? 'class-info (car x)))) + sasm)) + +(define *sasm-transform-code-module-count* 0) + +(define (sasm-transform-code sasm-program) + (define (get-module) + (let ((module + (string-append "module" + (number->string *sasm-transform-code-module-count*)))) + (set! *sasm-transform-code-module-count* (+ 1 *sasm-transform-code-module-count*)) + module)) + (let ((ast (sasm-parse-program sasm-program))) + (if (not ast) + (error "SASM source parse error")) + (if (not (sasm-program-analyze-symbols! (get-module) ast)) + (error "One or more SASM errors detected"))) + (map sasm-transform-statement + (sasm-remove-directives sasm-program))) + +(define (sasm-transform-port port) + (sasm-transform-code (sasm-read-port (sasm-assemble-interactive-context) port))) + +(define (sasm-transform-file file-name) + (if *sasm-output-progress* + (begin (display ";; starting scan of input file " + (current-output-port)) + (display file-name + (current-output-port)) + (newline (current-output-port)))) + (let ((code (sasm-read-file file-name))) + (if *sasm-output-progress* + (begin (display ";; finished scan of input file " + (current-output-port)) + (display file-name + (current-output-port)) + (newline (current-output-port)))) + (sasm-transform-code (sasm-read-file file-name)))) + +(define (sasm-write-transform-port code port) + (error "Unexpected!") + (for-each (lambda (x) (write x port)) + code)) + +(define (sasm-transform-statement sasm-code) + (case (car sasm-code) + ((class entry global export extern) + (if *sasm-output-progress* + (begin (display ";; transform directive: " + (current-output-port)) + (display (car sasm-code) + (current-output-port)) + (newline (current-output-port)))) + sasm-code) + ((function) + (if *sasm-output-progress* + (begin + (display ";; starting function " + (current-output-port)) + (display (+ *sasm-transform-function-count* 1) + (current-output-port)) + (display ": " + (current-output-port)) + (display (cadr (list-ref sasm-code 1)) + (current-output-port)) + (newline (current-output-port)))) + (let ((func (sasm-transform-function sasm-code))) + (if *sasm-output-progress* + (begin + (display ";; finished function " + (current-output-port)) + (set! *sasm-transform-function-count* + (+ *sasm-transform-function-count* 1)) + (display *sasm-transform-function-count* + (current-output-port)) + (display ": " + (current-output-port)) + (display (cadr (list-ref sasm-code 1)) + (current-output-port)) + (newline (current-output-port))) + #f) + func)) + ((define-symconst) + (sasm-symconst-alist-append (cdr sasm-code)) + sasm-code) + ((include) (error "include directive is not allowed")) + (else + (error "Invalid SASM statement " sasm-code)))) + +(define (sasm-fix-locals n-locals sasm-code) + (map (lambda (stmt) + (if (and (equal? 'perform (list-ref stmt 0)) + (equal? '(op reserve-locals) (list-ref stmt 1))) + `(perform (op reserve-locals) (const ,n-locals)) + stmt)) + sasm-code)) + +(define (sasm-temp-max sasm-code) + (let ((nums (filter-map (lambda (x) + (and (list? x) + (= 2 (length x)) + (equal? 'temp (car x)) + (number? (cadr x)) + (cadr x))) + (apply append sasm-code)))) + (if (null? nums) + 0 + (+ 1 (apply max nums))))) + +(define (sasm-local-max sasm-code) + (let ((nums (filter-map (lambda (x) + (and (list? x) + (= 2 (length x)) + (or (equal? 'local (car x)) + (equal? 'n-locals (car x))) + (+ 1 (cadr x)))) + (apply append sasm-code))) + (decl (apply max + 0 + (filter-map (lambda (x) + (and (equal? 'perform (car x)) + (equal? '(op reserve-locals) (list-ref x 1)) + (equal? 'const (car (list-ref x 2))) + (cadr (list-ref x 2)))) + sasm-code)))) + (apply max decl nums))) + +(define (sasm-optimize-simple sasm-code) + (define (sasm-optimize-insn insn) + (if (pattern-match `(assign (? dest) (reg (? dest))) insn) + '() + (list insn))) + (apply append (map sasm-optimize-insn sasm-code))) + +(define (sasm-optimize sasm-code) + (if *sasm-regalloc-cheap* + (sasm-regalloc-cheap sasm-code) + (if *sasm-enable-only-regalloc* + (sasm-regalloc-transform sasm-code) + (let ((opt-code (sasm-dataflow-optimize (sasm-optimize-simple sasm-code)))) + (if *sasm-enable-regalloc* + (sasm-regalloc-transform opt-code) + opt-code))))) + +(define (sasm-transform-function sasm-function) + (define (lookup attrib) + (case attrib + ((name locals) + (cadr (assoc attrib (cdr sasm-function)))) + ((body) + (cdr (assoc 'body (cdr sasm-function)))) + (else + (error "Invalid attribute -- SASM-TRANSFORM" attrib)))) + (define (rewrite-stmts stmts level top result) + (if (null? stmts) + (let ((rewritten (reverse result))) + (let ((opt-code (sasm-optimize (sasm-symconst-preprocess-code (sasm-fix-locals (sasm-local-max rewritten) + rewritten))))) + `((locals ,(max top (sasm-local-max opt-code))) + (body ,@opt-code)))) + (let ((stmt (car stmts))) + (define (as-reg x) + (cond ((symbol? x) + `(reg ,x)) + ((and (list? x) + (eqv? 'reg (car x)) + (= 2 (length x)) + (symbol? (list-ref x 1))) + x) + (else + (error "Invalid register " x stmt)))) + (case (car stmt) + ((save) + (rewrite-stmts (cdr stmts) (+ level 1) (max top (+ level 1)) + (cons `(assign (local ,level) + ,(as-reg (cadr stmt))) + result))) + ((restore) + (rewrite-stmts (cdr stmts) (- level 1) top + (cons `(assign ,(as-reg (cadr stmt)) + (local ,(- level 1))) + result))) + (else + (rewrite-stmts (cdr stmts) level top (cons stmt result))))))) + `(function (name ,(lookup 'name)) + ,@(rewrite-stmts (lookup 'body) (lookup 'locals) (lookup 'locals) '()))) + diff --git a/src/sasm/sasm-dataflow.scm b/src/sasm/sasm-dataflow.scm new file mode 100644 index 0000000..1a79038 --- /dev/null +++ b/src/sasm/sasm-dataflow.scm @@ -0,0 +1,1185 @@ +;; sasm-dataflow.scm +;; Dataflow analysis for SASM + +(need util/list) +(need util/vector) +(need sasm/fastset) +(need algo/graph) +(need sasm/fastgraph) + +;; TODO: +;; Dataflow analysis is currently oblivious of tree-structured SASM statements. +;; For tree-structured expressions to be a first-class SASM feature, this module +;; needs to be modified to recognize them. A better abstraction of SASM statement +;; syntax obviously needs to be developed. +;; + +;; OPT: +;; Incremental dataflow analysis would be the single most important optimization that +;; could be done for SASM. This would be a big investment but would have a big reward. +;; +;; Basic-block optimization would be a significant investment as well, with I'm guessing +;; a smaller payoff. +;; + +;; +;; Determines if a given pointer into a SASM block ends the current +;; basic block. The 'start-pointer' is the list of instructions +;; where the basic-block started. The 'current-pointer' is the +;; list of instructions from the current instruction to the +;; end of the instruction block. +;; +(define (sasm-ends-basic-block? start-pointer current-pointer) + (cond + ((null? current-pointer) + #t) + (else + (case (car (car current-pointer)) + ((label) + (let ((insns (memq-reverse (car current-pointer) start-pointer))) + (not (accum (lambda (a b) (and a (eqv? 'label (car b)))) + '() + insns)))) + ((goto branch branch-false branch-true branch-zero branch-nonzero) #t) + (else + (and (not (null? (cdr current-pointer))) + (eqv? 'label (car (car (cdr current-pointer))))) ))))) + +(define (sasm-split-basic-blocks sasm-code) + (define (iter result bb-cursor bb-start) + (cond ((null? bb-cursor) + (reverse (if (null? bb-start) + result + (cons (basic-block bb-start) result)))) + ((sasm-ends-basic-block? bb-start bb-cursor) + (iter (cons (basic-block (reverse (memq-reverse (car bb-cursor) + bb-start))) + result) + (cdr bb-cursor) + (cdr bb-cursor))) + (else + (iter result (cdr bb-cursor) bb-start)))) + (define (basic-block insns) + insns) + (iter '() sasm-code sasm-code)) + +(define (sasm-basic-block-entry-points basic-block) + (let iter ((insns basic-block) (result '())) + (cond ((or (null? insns) + (not (eqv? 'label (car (car insns))))) + result) + (else + (iter (cdr insns) (cons (list-ref (car insns) 1) result)))))) + +(define (sasm-statement-exit-points sasm-stmt) + (case (car sasm-stmt) + ((return) + (list)) + ((branch branch-true branch-false branch-zero branch-nonzero) + (list #f (list-ref (list-ref sasm-stmt 1) 1))) + ((goto) + (if (equal? 'label (car (list-ref sasm-stmt 1))) + (list (list-ref (list-ref sasm-stmt 1) 1)) ;; intraproc goto + (list) )) ;; interproc tailcall + (else + (list #f)))) + +(define (sasm-basic-block-exit-points basic-block) + (let ((end (terminal-pair basic-block))) + (and end + (sasm-statement-exit-points (car end))))) + +(define (sasm-statement-link sasm-code sasm-stmt exit-point) + (if (not exit-point) + (let ((rest (memq sasm-stmt sasm-code))) + (cond ((not rest) (error "Invalid SASM statement -- sasm-statement-link")) + ((null? (cdr rest)) (error "SASM statement has no 'next' link -- sasm-statement-link")) + (else (cadr rest)))) + (let ((insns (member `(label ,exit-point) sasm-code))) + (if insns + (car insns) + (error "Unable to resolve label -- sasm-statement-link" exit-point))))) + +(define (sasm-basic-block-link basic-blocks current-block exit-point) + (if (not exit-point) + (let ((rest (memq current-block basic-blocks))) + (cond ((not rest) (error "Invalid basic-block -- sasm-basic-block-link")) + ((null? (cdr rest)) (error "Basic block has no 'next' node -- sasm-basic-block-link" + current-block exit-point)) + (else (cadr rest)))) + (let ((lookup (filter (lambda (bb) (member exit-point + (sasm-basic-block-entry-points bb))) + basic-blocks))) + (if (> (length lookup) 1) + (error "Ambiguous exit-point -- sasm-basic-block-link") + (car lookup))))) + +(define (sasm-statement-id sasm-code stmt) + (let ((entry (memq stmt sasm-code))) + (if (not entry) + (error "Unable to compute statement ID -- sasm-statement-id" stmt) + (- (length sasm-code) (length entry))))) + +(define (sasm-basic-block-id basic-blocks current-basic-block) + (let ((entry (memq current-basic-block basic-blocks))) + (if entry + (- (length basic-blocks) (length entry)) + (error "Invalid basic-block, doesn't have ID wrt basic-blocks -- sasm-basic-block-id")))) + +(define (sasm-lookup-statement-by-id sasm-code id) + (list-ref sasm-code id)) + +(define (sasm-lookup-basic-block-by-id basic-blocks id) + (list-ref basic-blocks id)) + +(define (sasm-build-control-flow-graph-from-basic-blocks basic-blocks) + (map (lambda (bb) + (cons (sasm-basic-block-id basic-blocks bb) + (map (lambda (exit-point) + (sasm-basic-block-id basic-blocks + (sasm-basic-block-link basic-blocks bb exit-point))) + (sasm-basic-block-exit-points bb)))) + basic-blocks)) + +(define (sasm-build-control-flow-graph-from-statements sasm-code) + (map (lambda (stmt) + (cons (sasm-statement-id sasm-code stmt) + (map (lambda (exit-point) + (sasm-statement-id sasm-code + (sasm-statement-link sasm-code stmt exit-point))) + (sasm-statement-exit-points stmt)))) + sasm-code)) + +(define (sasm-print-dataflow-information sasm-code) + (sasm-print-dataflow-information-for-basic-blocks (sasm-split-basic-blocks sasm-code))) + +(define (sasm-print-dataflow-information-for-basic-blocks basic-blocks) + (let ((cgf (sasm-build-control-flow-graph-from-basic-blocks basic-blocks))) + (for-each (lambda (bb cgf-node) + (display "== BASIC BLOCK ") + (display (sasm-basic-block-id basic-blocks bb)) + (display " ==\n") + (if (not (= (sasm-basic-block-id basic-blocks bb) + (car cgf-node))) + (error "Invalid CGF! " + (sasm-basic-block-id basic-blocks bb) + (car cgf-node))) + (display "links to:") + (for-each (lambda (x) (display " ") (display x)) + (cdr cgf-node)) + (newline) + (display "entry points:") + (for-each (lambda (x) (display " ") (display x)) + (sasm-basic-block-entry-points bb)) + (newline) + (for-each (lambda (x) (display " ") (write x) (newline)) + bb) + (newline) + (newline)) + basic-blocks + cgf))) + +;; reaching definitions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (sasm-reachdef-id sasm-code stmt) + (sasm-statement-id sasm-code stmt)) + +(define (sasm-reachdef-statement-defines stmt) + (case (car stmt) + ((assign) + (list (list-ref stmt 1))) + ((perform) + (case (cadr (list-ref stmt 1)) + ((store-local) + (list (list 'local (cadr (list-ref stmt 2))))) + ((store-arg) + (list (list 'arg (cadr (list-ref stmt 2))))) + ((call tail-call this-call) + '((reg accum) (reg operand) (reg index) (reg this))) + (else + #f))) + (else #f))) + +(define (sasm-reachdef-compute-defs sasm-code def) + (accum append + '() + (filter-map (lambda (stmt) + (let ((d (sasm-reachdef-statement-defines stmt))) + (and d + (not (null? (intersect-lists equal? def d))) + (map (lambda (x) (cons (sasm-reachdef-id sasm-code stmt) + x)) + (intersect-lists equal? def d))))) + sasm-code))) + +(define (sasm-reachdef-compute-gens sasm-code) + (map (lambda (stmt) + (if (sasm-reachdef-statement-defines stmt) + (map (lambda (x) (cons (sasm-reachdef-id sasm-code stmt) x)) + (sasm-reachdef-statement-defines stmt)) + '())) + sasm-code)) + +(define (sasm-reachdef-compute-kills sasm-code) + (let ((gens (sasm-reachdef-compute-gens sasm-code))) + (map (lambda (stmt) + (let ((def (sasm-reachdef-statement-defines stmt))) + (if def + (subtract-lists equal? + (sasm-reachdef-compute-defs sasm-code def) + (map (lambda (x) (cons (sasm-reachdef-id sasm-code stmt) + x)) + def)) + '()))) + sasm-code))) + +;; +;; Dataflow equations for reaching definitions: +;; +;; (in-set n) = (accum-union p +;; (predecessors n) +;; (out-set p)) +;; +;; (out-set n) = (union (gen-set n) +;; (minus (in-set n) (kill-set n))) +;; +(define (sasm-slow-reachdef-compute sasm-code) + (let ((g (sasm-build-control-flow-graph-from-statements sasm-code)) + (nodes (map (lambda (stmt) (sasm-reachdef-id sasm-code stmt)) sasm-code)) + (gen-sets (sasm-reachdef-compute-gens sasm-code)) + (kill-sets (sasm-reachdef-compute-kills sasm-code))) + (define (compute-in-sets nodes in-sets out-sets) + (map (lambda (node) + (accum (list-unioner equal?) + '() + (map (lambda (x) (list-ref out-sets x)) + (graph-predecessors g node)))) + nodes)) + (define (compute-out-sets nodes in-sets out-sets) + (map (lambda (node) + (union-lists equal? + (list-ref gen-sets node) + (subtract-lists equal? + (list-ref in-sets node) + (list-ref kill-sets node)))) + nodes)) + (define (sets-equal? a b) + (list-set=? equal? a b)) + (define (meta-sets-equal? a b) + (all? (lambda (x) x) + (map sets-equal? a b))) + (define (iterate nodes in-sets out-sets) + (let ((next-in (compute-in-sets nodes in-sets out-sets))) + (let ((next-out (compute-out-sets nodes next-in out-sets))) + (if (and (meta-sets-equal? in-sets next-in) + (meta-sets-equal? out-sets next-out)) + (list next-in next-out) + (iterate nodes next-in next-out))))) + (iterate nodes + (map (lambda (x) '()) + nodes) + (map (lambda (x) '()) + nodes)))) + +(define (sasm-fast-reachdef-compute sasm-code) + (let* ((g (sasm-build-control-flow-graph-from-statements sasm-code)) + (g-elem (graph-elements g)) + (nodes (list->vector g-elem)) + (n-nodes (vector-length nodes)) + + (parents (list->vector (map (lambda (elem) + (graph-predecessors g elem)) + g-elem))) + (gen-sets (sasm-reachdef-compute-gens sasm-code)) + (kill-sets (sasm-reachdef-compute-kills sasm-code)) + + (symset (accum append '() gen-sets)) + + (imp (fastset-importer symset)) + (exp (fastset-exporter imp symset)) + (empty-fastset (fastset-collapse imp '())) + + (gen-fs (list->vector (map (lambda (x) (fastset-collapse imp x)) + gen-sets))) + (kill-fs (list->vector (map (lambda (x) (fastset-collapse imp x)) + kill-sets)))) + + (define (compute-in-sets in-sets out-sets) + (vector-map (lambda (node) + (accum-map fastset-union + empty-fastset + (lambda (n) (vector-ref out-sets n)) + (vector-ref parents node))) + nodes)) + + (define (compute-out-sets in-sets out-sets) + (vector-map (lambda (node) + (fastset-union (vector-ref gen-fs node) + (fastset-subtract (vector-ref in-sets node) + (vector-ref kill-fs node)))) + nodes)) + + (define (meta-sets-equal? a b) + (let ((n (vector-length a))) + (let loop ((i 0)) + (or (>= i n) + (and (fastset-equal? (vector-ref a i) (vector-ref b i)) + (loop (+ i 1))))))) + + (define (expand-sets the-set) + (map (lambda (x) (fastset-expand exp x)) + (vector->list the-set))) + + (define (iterate in-sets out-sets) + (let* ((next-in (compute-in-sets in-sets out-sets)) + (next-out (compute-out-sets next-in out-sets))) + (if (and (meta-sets-equal? in-sets next-in) + (meta-sets-equal? out-sets next-out)) + (list (expand-sets next-in) (expand-sets next-out)) + (iterate next-in next-out)))) + + (iterate (make-vector n-nodes empty-fastset) + (make-vector n-nodes empty-fastset)) + + )) + +(define (sasm-reachdef-compute sasm-code) + (sasm-fast-reachdef-compute sasm-code)) + +(define (sasm-strong-reachdef-compute-without sasm-code) + (sasm-strong-reachdef-compute (sasm-reachdef-compute sasm-code) sasm-code)) + +(define (sasm-strong-reachdef-compute reachdef sasm-code) + (let* ((g (sasm-build-control-flow-graph-from-statements sasm-code)) + (nodes (map (lambda (stmt) (sasm-statement-id sasm-code stmt)) sasm-code)) + (gen-sets (sasm-reachdef-compute-gens sasm-code)) + (reachdef-in (list-ref reachdef 0)) + (reachdef-out (list-ref reachdef 1))) + (define (compute-in-sets nodes in-sets out-sets) + (map (lambda (node) + (let ((parents (graph-predecessors g node))) + (if (null? parents) + '() + (accum (list-intersecter equal?) + (list-ref out-sets (car parents)) + (map (lambda (x) (list-ref out-sets x)) + (cdr parents)))))) + nodes)) + (define (compute-out-sets nodes in-sets out-sets) + (map (lambda (node) + (intersect-lists equal? + (list-ref reachdef-out node) + (union-lists equal? + (list-ref in-sets node) + (list-ref gen-sets node)))) + nodes)) + (define (sets-equal? a b) + (list-set=? equal? a b)) + (define (meta-sets-equal? a b) + (all? (lambda (x) x) + (map sets-equal? a b))) + (define (iterate nodes in-sets out-sets) + (let ((next-in (compute-in-sets nodes in-sets out-sets))) + (let ((next-out (compute-out-sets nodes next-in out-sets))) + (if (and (meta-sets-equal? in-sets next-in) + (meta-sets-equal? out-sets next-out)) + (list next-in next-out) + (iterate nodes next-in next-out))))) + (iterate nodes + reachdef-in + reachdef-out))) + +;; available expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (sasm-availexp-available-expression stmt) + (case (car stmt) + ((assign) + (if (equal? 'op (car (list-ref stmt 2))) + (case (cadr (list-ref stmt 2)) + ((load-array load-arg load-local) + #f) + (else + (cddr stmt))) + #f)) + (else #f))) + +(define (sasm-availexp-killed-expressions stmt) + (sasm-reachdef-statement-defines stmt)) + +(define (sasm-availexp-all-expressions sasm-code) + (remove-duplicates equal? + (filter-map sasm-availexp-available-expression + sasm-code))) + +(define (sasm-availexp-compute-kills sasm-code) + (let ((all (sasm-availexp-all-expressions sasm-code))) + (map (lambda (stmt) + (let ((kills (sasm-availexp-killed-expressions stmt))) + (if kills + (filter-map (lambda (exp) + (let loop ((kills kills)) + (cond ((null? kills) + #f) + ((member (car kills) exp) + exp) + (else + (loop (cdr kills)))))) + all) + '()))) + sasm-code))) + +(define (sasm-availexp-compute-gens sasm-code) + (let ((kills (sasm-availexp-compute-kills sasm-code))) + (map (lambda (stmt kill) + (let ((avail (sasm-availexp-available-expression stmt))) + (if avail + (subtract-lists equal? + (list avail) + kill) + '()))) + sasm-code + kills))) + +(define (sasm-availexp-compute sasm-code) + (let ((g (sasm-build-control-flow-graph-from-statements sasm-code)) + (all (sasm-availexp-all-expressions sasm-code)) + (nodes (map (lambda (stmt) (sasm-statement-id sasm-code stmt)) sasm-code)) + (gen-sets (sasm-availexp-compute-gens sasm-code)) + (kill-sets (sasm-availexp-compute-kills sasm-code))) + (define (compute-in-sets nodes in-sets out-sets) + (map (lambda (node) + (let ((parents (graph-predecessors g node))) + (if (null? parents) + '() + (accum (list-intersecter equal?) + (list-ref out-sets (car parents)) + (map (lambda (x) (list-ref out-sets x)) + (cdr parents)))))) + nodes)) + (define (compute-out-sets nodes in-sets out-sets) + (map (lambda (node) + (union-lists equal? + (list-ref gen-sets node) + (subtract-lists equal? + (list-ref in-sets node) + (list-ref kill-sets node)))) + nodes)) + (define (sets-equal? a b) + (list-set=? equal? a b)) + (define (meta-sets-equal? a b) + (all? (lambda (x) x) + (map sets-equal? a b))) + (define (iterate nodes in-sets out-sets) + (let ((next-in (compute-in-sets nodes in-sets out-sets))) + (let ((next-out (compute-out-sets nodes next-in out-sets))) + (if (and (meta-sets-equal? in-sets next-in) + (meta-sets-equal? out-sets next-out)) + (list next-in next-out) + (iterate nodes next-in next-out))))) + (iterate nodes + ; initialize all sets other than the start node's in-set to all + (map (lambda (x) (if (zero? x) '() all)) + nodes) + (map (lambda (x) all) + nodes)))) + +(define (sasm-availexp-compute-kills-id sasm-code) + (map (lambda (stmt-a) + (let ((kills (sasm-availexp-killed-expressions stmt-a))) + (filter-map (lambda (stmt-b) + (and (not (eq? stmt-a stmt-b)) + (sasm-availexp-available-expression stmt-b) + kills + (let loop ((kills kills)) + (and (not (null? kills)) + (or (member (car kills) (sasm-availexp-available-expression stmt-b)) + (loop (cdr kills))))) + (sasm-statement-id sasm-code stmt-b))) + sasm-code))) + sasm-code)) + +(define (sasm-availexp-compute-gens-id sasm-code) + (let ((kills (sasm-availexp-compute-kills-id sasm-code))) + (map (lambda (stmt kill) + (let ((avail (sasm-availexp-available-expression stmt))) + (if avail + (subtract-lists equal? + (list (sasm-statement-id sasm-code stmt)) + kill) + '()))) + sasm-code + kills))) + +(define (sasm-availexp-id-compute sasm-code) + (let ((g (sasm-build-control-flow-graph-from-statements sasm-code)) + (all (sasm-availexp-all-expressions sasm-code)) + (nodes (map (lambda (stmt) (sasm-statement-id sasm-code stmt)) sasm-code)) + (gen-sets (sasm-availexp-compute-gens-id sasm-code)) + (kill-sets (sasm-availexp-compute-kills-id sasm-code))) + (define (compute-in-sets nodes in-sets out-sets) + (map (lambda (node) + (let ((parents (graph-predecessors g node))) + (if (null? parents) + '() + (accum (list-intersecter equal?) + (list-ref out-sets (car parents)) + (map (lambda (x) (list-ref out-sets x)) + (cdr parents)))))) + nodes)) + (define (compute-out-sets nodes in-sets out-sets) + (map (lambda (node) + (union-lists equal? + (list-ref gen-sets node) + (subtract-lists equal? + (list-ref in-sets node) + (list-ref kill-sets node)))) + nodes)) + (define (sets-equal? a b) + (list-set=? equal? a b)) + (define (meta-sets-equal? a b) + (all? (lambda (x) x) + (map sets-equal? a b))) + (define (iterate nodes in-sets out-sets) + (let ((next-in (compute-in-sets nodes in-sets out-sets))) + (let ((next-out (compute-out-sets nodes next-in out-sets))) + (if (and (meta-sets-equal? in-sets next-in) + (meta-sets-equal? out-sets next-out)) + (list next-in next-out) + (iterate nodes next-in next-out))))) + (iterate nodes + ; initialize all sets other than the start node's in-set to all + (map (lambda (x) (if (zero? x) '() all)) + nodes) + (map (lambda (x) all) + nodes)))) + +;; liveness ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; +;; == SASM statement types == +;; return +;; label +;; assign +;; perform +;; test +;; [REWRITE] save +;; [REWRITE] restore +;; push +;; pop +;; branch +;; branch-true +;; branch-false +;; branch-zero +;; branch-nonzero +;; goto +;; +;; == SASM expression types == +;; reg temp arg local const label +;; + +;; TODO: change (op call) into (op this-call) and (op static-call) +;; + +(define (sasm-liveness-statement-gens stmt) + (define (rvalues stmt) + (accum append + '() + (filter-map (lambda (x) + (and (list? x) + (case (car x) + ((reg temp arg local sys) + (list x)) + ((result) + (rvalues (cdr x))) + (else #f)))) + stmt))) + (cond ((equal? 'assign (car stmt)) + (rvalues (cddr stmt))) + ((equal? 'return (car stmt)) + (list '(reg accum) '(sys frame-pointer) '(sys stack-pointer))) + ((and (equal? 'perform (car stmt)) + (= 3 (length stmt)) + (or (equal? '(op this-call) (list-ref stmt 1)) + (and (equal? '(op call) (list-ref stmt 1)) + (not (equal? 'const (car (list-ref stmt 2))))))) + (remove-duplicates equal? + (cons '(reg this) + (rvalues stmt)))) + ((and (equal? 'perform (car stmt)) + (>= (length stmt) 3) + (equal? '(op tail-call) (list-ref stmt 1)) + (not (equal? 'const (car (list-ref stmt 2))))) + (if (not (= 5 (length stmt))) + (error "Unrecognized tail-call stmt " stmt)) + (remove-duplicates equal? + (cons '(reg this) + (rvalues stmt)))) + (else + (rvalues stmt)))) + +(define (sasm-liveness-statement-kills stmt) + (let ((defs (sasm-reachdef-statement-defines stmt))) + (if defs + defs + '()))) + +(define (sasm-liveness-compute-gens sasm-code) + (map sasm-liveness-statement-gens sasm-code)) + +(define (sasm-liveness-compute-kills sasm-code) + (map sasm-liveness-statement-kills sasm-code)) + +(define (sasm-liveness-compute sasm-code) + (let* ((g (sasm-build-control-flow-graph-from-statements sasm-code)) + (g-elem (graph-elements g)) + (nodes (list->vector g-elem)) + (n-nodes (vector-length nodes)) + (children (list->vector (map (lambda (elem) + (graph-successors g elem)) + g-elem))) + (@gen-sets (sasm-liveness-compute-gens sasm-code)) + (@kill-sets (sasm-liveness-compute-kills sasm-code)) + (symset (remove-duplicates equal? + (accum append + '() + (append @gen-sets + @kill-sets)))) + ;; function to import a symbol into the fastset + (import-symbol (fastset-importer symset)) + ;; function to export a symbol from the fastset + (export-symbol (fastset-exporter import-symbol symset)) + (empty-fastset (fastset-collapse import-symbol '())) + ;; The gen-sets list as a vector of fastset elements + (gen-fastsets (list->vector (map (lambda (x) + (fastset-collapse import-symbol + x)) + @gen-sets))) + (kill-fastsets (list->vector (map (lambda (x) + (fastset-collapse import-symbol + x)) + @kill-sets))) + ) + (define (compute-in-sets in-sets out-sets) + (vector-map (lambda (node) + (fastset-union (vector-ref gen-fastsets node) + (fastset-subtract (vector-ref out-sets + node) + (vector-ref kill-fastsets + node)))) + nodes)) + (define (compute-out-sets in-sets out-sets) + (vector-map (lambda (node) + (accum-map fastset-union + empty-fastset + (lambda (n) (vector-ref in-sets n)) + (vector-ref children node))) + nodes)) + (define (meta-sets-equal? a b) + (let ((n (vector-length a))) + (let loop ((i 0)) + (or (>= i n) + (and (fastset-equal? (vector-ref a i) (vector-ref b i)) + (loop (+ i 1))))))) + (define (expand-sets the-set) + (map (lambda (x) (fastset-expand export-symbol x)) + (vector->list the-set))) + (define (iterate in-sets out-sets) + (let ((next-out (compute-out-sets in-sets out-sets))) + (let ((next-in (compute-in-sets in-sets next-out))) + (if (and (meta-sets-equal? in-sets next-in) + (meta-sets-equal? out-sets next-out)) + (list (expand-sets next-in) + (expand-sets next-out)) + (iterate next-in next-out))))) + (iterate (make-vector n-nodes empty-fastset) + (make-vector n-nodes empty-fastset)) + )) + +(define (sasm-liveness-compute-slow sasm-code) + (let* ((g (sasm-build-control-flow-graph-from-statements sasm-code)) + (nodes (map (lambda (stmt) (sasm-statement-id sasm-code stmt)) + sasm-code)) + (gen-sets (sasm-liveness-compute-gens sasm-code)) + (kill-sets (sasm-liveness-compute-kills sasm-code)) + (symset (accum append '() gen-sets)) + ;; function to import a symbol into the fastset + (import-symbol (fastset-importer symset)) + ;; function to export a symbol from the fastset + (export-symbol (fastset-exporter import-symbol symset)) + ;; The gen-sets vector as a + ) + (define (compute-in-sets nodes in-sets out-sets) + (map (lambda (node) + (union-lists equal? + (list-ref gen-sets node) + (subtract-lists equal? + (list-ref out-sets node) + (list-ref kill-sets node)))) + nodes)) + (define (compute-out-sets nodes in-sets out-sets) + (map (lambda (node) + (accum (list-unioner equal?) + '() + (map (lambda (x) (list-ref in-sets x)) + (graph-successors g node)))) + nodes)) + (define (sets-equal? a b) + (list-set=? equal? a b)) + (define (meta-sets-equal? a b) + (all? (lambda (x) x) + (map sets-equal? a b))) + (define (iterate nodes in-sets out-sets) + (let ((next-out (compute-out-sets nodes in-sets out-sets))) + (let ((next-in (compute-in-sets nodes in-sets next-out))) + (if (and (meta-sets-equal? in-sets next-in) + (meta-sets-equal? out-sets next-out)) + (list next-in next-out) + (iterate nodes next-in next-out))))) + (iterate nodes + (map (lambda (x) '()) + nodes) + (map (lambda (x) '()) + nodes)))) + +(define (sasm-dataflow-annotate sasm-code) + (sasm-dataflow-annotate-prefix " " sasm-code)) + +(define (sasm-dataflow-annotate-prefix prefix sasm-code) + (let ((reachdef (sasm-reachdef-compute sasm-code)) + (availexp (sasm-availexp-compute sasm-code)) + (liveness (sasm-liveness-compute sasm-code))) + (define (pre-data data) + (car data)) + (define (post-data data) + (cadr data)) + (define (println-iter l) + (if (null? l) + (newline) + (begin (display " ") + (display (car l)) + (println-iter (cdr l))))) + (define (println msg l) + (display prefix) + (display msg) + (println-iter l)) + (define (print-header header reach avail live) + (if (or (not (null? reach)) + (not (null? avail)) + (not (null? live))) + (println header '()))) + (define (print-info reach avail live) + (if (not (null? reach)) + (println ";; Reaching definitions:" reach)) + (if (not (null? avail)) + (println ";; Available expressions:" avail)) + (if (not (null? live)) + (println ";; Live values:" live)) ) + (let iter ((insns sasm-code) + (both? #t) + (first? #t) + (r-pre (pre-data reachdef)) + (r-post (post-data reachdef)) + (a-pre (pre-data availexp)) + (a-post (post-data availexp)) + (l-pre (pre-data liveness)) + (l-post (post-data liveness))) + (if (null? insns) + #t + (let* ((next? (not (null? (cdr insns)))) + (both-next? (and next? + (not (and + (list-set=? equal? + (car r-post) + (cadr r-pre)) + (list-set=? equal? + (car a-post) + (cadr a-pre)) + (list-set=? equal? + (car l-post) + (cadr l-pre))))))) + (if (and both? (not first?)) + (print-header ";; === Pre-Statement ===" + (car r-pre) (car a-pre) (car l-pre))) + (if both? + (print-info (car r-pre) (car a-pre) (car l-pre))) + (display prefix) + (write (car insns)) + (display " ;; ") + (display (sasm-statement-id sasm-code (car insns))) + (newline) + (if both-next? + (print-header ";; === Post-Statement ===" + (car r-post) (car a-post) (car l-post))) + (print-info (car r-post) (car a-post) (car l-post)) + (iter (cdr insns) + both-next? + #f + (cdr r-pre) + (cdr r-post) + (cdr a-pre) + (cdr a-post) + (cdr l-pre) + (cdr l-post))))))) + +;; transform: constant propagation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (sasm-statement-fold-constants sasm-stmt) + (define (const? exp) + (eqv? 'const (car exp))) + (define (const exp) + (list-ref exp 1)) + (define (known? op) + (member (cadr op) '(add sub mul))) + (define (fold op x y) + (case (cadr op) + ((add) (+ (const x) (const y))) + ((sub) (- (const x) (const y))) + ((mul) (* (const x) (const y))) + (else (error "unknown fold operation" op)))) + (if (and (eqv? 'assign (car sasm-stmt)) + (eqv? 'op (car (list-ref sasm-stmt 2))) + (= 5 (length sasm-stmt)) + (known? (list-ref sasm-stmt 2)) + (const? (list-ref sasm-stmt 3)) + (const? (list-ref sasm-stmt 4))) + `(assign ,(list-ref sasm-stmt 1) + (const ,(fold (list-ref sasm-stmt 2) + (list-ref sasm-stmt 3) + (list-ref sasm-stmt 4)))) + sasm-stmt)) + +(define (map-rvalues proc sasm-stmt) + (case (car sasm-stmt) + ((push pop) + `(,(car sasm-stmt) + ,(proc (list-ref sasm-stmt 1)))) + ((test perform) + `(,(list-ref sasm-stmt 0) + ,(list-ref sasm-stmt 1) + ,@(map proc (cddr sasm-stmt)))) + ((assign) + (if (equal? 'op (car (list-ref sasm-stmt 2))) + `(assign ,(list-ref sasm-stmt 1) + ,(list-ref sasm-stmt 2) + ,@(map proc (cdddr sasm-stmt))) + `(assign ,(list-ref sasm-stmt 1) + ,(proc (list-ref sasm-stmt 2))))) + (else + sasm-stmt))) + +(define (sasm-statement-rvalue-known? sasm-code sasm-stmt reachdef rvalue) + (= 1 (length (filter (lambda (x) (equal? rvalue x)) + (map cdr (list-ref (car reachdef) + (sasm-statement-id sasm-code sasm-stmt))))))) + +(define (sasm-statement-rvalue-def-stmt sasm-code sasm-stmt reachdef rvalue) + (caar (filter (lambda (x) (equal? rvalue (cdr x))) + (list-ref (car reachdef) + (sasm-statement-id sasm-code sasm-stmt))))) + +(define (sasm-reachdef-by-rvalue stmt-reachdef rvalue) + (filter-map (lambda (x) (and (equal? rvalue (cdr x)) + (car x))) + stmt-reachdef)) + +(define (sasm-reachdef-by-multiple-rvalues stmt-reachdef rvalues) + (accum append + '() + (map (lambda (rvalue) (sasm-reachdef-by-rvalue stmt-reachdef rvalue)) + rvalues))) + +(define (sasm-statement-uses-rvalue? sasm-stmt rvalue) + (member rvalue (sasm-liveness-statement-gens sasm-stmt))) + +(define (sasm-statements-using-rvalue sasm-code rvalue) + (filter-map (lambda (stmt) + (and (sasm-statement-uses-rvalue? stmt rvalue) + (sasm-statement-id sasm-code stmt))) + sasm-code)) + +(define (sasm-statement-rvalue-def-avail? sasm-code ref-code sasm-stmt reachdef reachdef-soft availexp rvalue) + (and (sasm-statement-rvalue-known? sasm-code sasm-stmt reachdef rvalue) + (let ((candidate (sasm-statement-rvalue-def-stmt sasm-code sasm-stmt reachdef rvalue))) + (and (member candidate + (list-ref (car availexp) + (sasm-statement-id sasm-code sasm-stmt))) + (let* ((new-stmt (list-ref ref-code candidate)) + (used (sasm-liveness-statement-gens new-stmt)) + (in-candidate (sasm-reachdef-by-multiple-rvalues (list-ref (car reachdef-soft) + candidate) + used)) + (in-current (sasm-reachdef-by-multiple-rvalues (list-ref (car reachdef-soft) + (sasm-statement-id sasm-code sasm-stmt)) + used))) + (list-set=? equal? + in-candidate + in-current)))))) + +(define (sasm-statement-rvalue-def-fold-rhs sasm-code ref-code sasm-stmt reachdef availexp rvalue) + (let ((known (sasm-statement-rvalue-def-stmt sasm-code sasm-stmt reachdef rvalue))) + (cons 'result (cddr (list-ref ref-code known))))) + +(define (sasm-const-prop-iter sasm-code) + (let ((reachdef (sasm-strong-reachdef-compute-without sasm-code))) + ;; to fold a r-value ref to a constant: + ;; + ;; 1. Only one definition of that r-value reaches this statement + ;; a. for each reaching definition, find the defined r-value + ;; b. filter those that are the same as the r-value in question + ;; c. if the list of matches is of length=1 + ;; 2. That definition must be a constant + ;; a. check that the definition is an const assignment + (define (fold-stmt stmt) + (let ((id (sasm-statement-id sasm-code stmt))) + (let ((reach (list-ref (car reachdef) id))) + (define (rvalue-known? rvalue) + (= 1 (length (filter (lambda (x) (equal? rvalue x)) + (map cdr reach))))) + (define (known-rvalue-def rvalue) + (caar (filter (lambda (x) (equal? rvalue (cdr x))) + reach))) + (define (known-rvalue-stmt rvalue) + (list-ref sasm-code (known-rvalue-def rvalue))) + (define (const-assignment? stmt) + (and (equal? (car stmt) 'assign) + (= 3 (length stmt)) + (equal? (car (list-ref stmt 2)) 'const))) + (sasm-statement-fold-constants + (map-rvalues (lambda (rvalue) + (if (and (rvalue-known? rvalue) + (const-assignment? (known-rvalue-stmt rvalue))) + (list-ref (known-rvalue-stmt rvalue) 2) + rvalue)) + stmt))))) + (map fold-stmt sasm-code))) + +(define (sasm-statements-defining sasm-code rvalue) + (filter-map (lambda (stmt) + (and (sasm-reachdef-statement-defines stmt) + (member rvalue (sasm-reachdef-statement-defines stmt)) + (cons (sasm-statement-id sasm-code stmt) + rvalue))) + sasm-code)) + +(define (sasm-copy-prop-iter sasm-code) + ;; to fold temporaries in a statement: + ;; + ;; (assign x y) ;; statement i + ;; ... + ;; ( x ) ;; statment j + ;; + ;; replace with + ;; + ;; (assign x y) ;; statement i + ;; ... + ;; ( y ) ;; statement j + ;; + ;; 1. Only one definition of the x reaches the statement, + ;; along all possible code paths + ;; a. for each reaching definition, find the defined r-value + ;; b. filter those that are the same as the r-value in question + ;; c. if the list of matches is of length=1, then OK + ;; 2. No definitions of y must reach statement j other than i, + ;; along any possible code path + ;; a. find the set of statements defining y + ;; b. intersect with the reachdef of statement i (alpha) + ;; c. intersect with the reachdef of statement j (beta) + ;; d. if alpha and beta are the same sets, then OK + ;; + (let* ((reachdef (sasm-reachdef-compute sasm-code)) + (strong-reachdef (sasm-strong-reachdef-compute reachdef sasm-code))) + (define (fold-stmt stmt) + (let ((id (sasm-statement-id sasm-code stmt))) + (let ((reach (list-ref (car strong-reachdef) id))) + (define (rvalue-known? rvalue) + (= 1 (length (filter (lambda (x) (equal? rvalue x)) + (map cdr reach))))) + (define (known-rvalue-def rvalue) + (caar (filter (lambda (x) (equal? rvalue (cdr x))) + reach))) + (define (known-rvalue-stmt rvalue) + (list-ref sasm-code (known-rvalue-def rvalue))) + (define (single-assignment? stmt) + (and (equal? (car stmt) 'assign) + (= 3 (length stmt)))) + (define (single-assignment-rvalue stmt) + (list-ref stmt 2)) + (sasm-statement-fold-constants + (map-rvalues (lambda (rvalue) + (if (and (rvalue-known? rvalue) + (let ((known-def (known-rvalue-def rvalue)) + (known-stmt (known-rvalue-stmt rvalue))) + (and known-def + known-stmt + (single-assignment? known-stmt) + (let* ((known-rvalue (single-assignment-rvalue known-stmt)) + (defs (sasm-statements-defining sasm-code known-rvalue))) +; (println "reach: " reach) +; (println "defs: " defs) +; (println "known-statement: " known-stmt) +; (println "s-a-r: " (single-assignment-rvalue known-stmt)) +; (println "id: " id) +; (println "kn: " known-def) +; (println "id-defs: " (list-ref (car reachdef) id)) +; (println "kn-defs: " (list-ref (car reachdef) known-def)) + (let ((result + (and (list-set=? equal? + (intersect-lists equal? + defs + (list-ref (car reachdef) id)) + (intersect-lists equal? + defs + (list-ref (car reachdef) known-def))) + (or ;#t + (not (equal? 'reg (car rvalue))) + (equal? 'reg (car known-rvalue)))))) +; (println "final-result: " result) +; (if result +; (println "replacing [" rvalue "] with [" (single-assignment-rvalue known-stmt) "] in " stmt)) +; (println) + result))))) + (single-assignment-rvalue (known-rvalue-stmt rvalue)) + rvalue)) + stmt))))) + (map fold-stmt sasm-code))) + +(define (sasm-deadcode-eliminate-iter sasm-code) + (let ((live-out (list-ref (sasm-liveness-compute sasm-code) 1))) + (filter (lambda (stmt) + ;; Deadcode: + ;; + ;; 1. Self-assignments + ;; 2. Assignments with targets that are not out-live + (and (not (and (equal? 'assign (car stmt)) + (= 3 (length stmt)) + (equal? (list-ref stmt 1) (list-ref stmt 2)))) + (or (not (equal? 'assign (car stmt))) + (member (list-ref stmt 1) + (list-ref live-out + (sasm-statement-id sasm-code stmt))) ))) + sasm-code))) + +(define (sasm-statements-generating-availexp sasm-code availexp) + (filter-map (lambda (stmt) + (and (sasm-availexp-available-expression stmt) + (equal? availexp (sasm-availexp-available-expression stmt)) + (sasm-statement-id sasm-code stmt))) + sasm-code)) + +(define (sasm-subexp-eliminate-iter sasm-code) + (let ((availexp-in (list-ref (sasm-availexp-id-compute sasm-code) 0))) + (define (copycat stmt) + (and (sasm-availexp-available-expression stmt) + (let ((parent-ids (filter-map (lambda (x) + (and (sasm-availexp-available-expression x) + (equal? (sasm-availexp-available-expression x) + (sasm-availexp-available-expression stmt)) + (sasm-statement-id sasm-code x))) + (map (lambda (x) (list-ref sasm-code x)) + (list-ref availexp-in (sasm-statement-id sasm-code stmt)))))) + (and (not (null? parent-ids)) + (list (car parent-ids) + (sasm-statement-id sasm-code stmt)))))) + (define (optimize stmt) + (let ((copy-id (copycat stmt))) + (if copy-id + (list copy-id) + '()))) + (define (iter remaining rewrite) + (if (null? remaining) + (rewrite-code sasm-code rewrite) + (iter (cdr remaining) + (append (optimize (car remaining)) + rewrite)))) + (define (rewrite-iter original-code new-code parent child) + (if (null? original-code) + (reverse new-code) + (let ((p-ent (assoc (sasm-statement-id sasm-code (car original-code)) parent)) + (c-ent (assoc (sasm-statement-id sasm-code (car original-code)) child))) + (cond ((and p-ent c-ent) + (rewrite-iter + (cdr original-code) + (cons `(assign (temp ,(cdr p-ent)) + ,(list-ref (car original-code) 1)) + (cons `(assign ,(list-ref (car original-code) 1) + (temp ,(cdr c-ent))) + new-code)) + parent + child)) + (p-ent + (rewrite-iter + (cdr original-code) + (cons `(assign (temp ,(cdr p-ent)) ,(list-ref (car original-code) 1)) + (cons (car original-code) + new-code)) + parent + child)) + (c-ent + (rewrite-iter + (cdr original-code) + (cons `(assign ,(list-ref (car original-code) 1) + (temp ,(cdr c-ent))) + new-code) + parent + child)) + (else + (rewrite-iter + (cdr original-code) + (cons (car original-code) + new-code) + parent + child)))))) + (define (rewrite-code sasm-code rewrite) + (let ((with-temps (map (let ((id (sasm-temp-max sasm-code))) + (lambda (x) + (let ((temp id)) + (set! id (+ id 1)) + (cons (cons (car x) temp) + (cons (cadr x) temp))))) + rewrite))) + (rewrite-iter sasm-code '() (map car with-temps) (map cdr with-temps)))) + (iter sasm-code '()))) + +(define (sasm-const-prop sasm-code) + (let iter ((cur-code sasm-code) + (new-code (sasm-const-prop-iter sasm-code))) + (if (equal? cur-code new-code) + cur-code + (iter new-code (sasm-const-prop-iter new-code))))) + +(define (sasm-copy-prop sasm-code) + (let iter ((cur-code sasm-code) + (new-code (sasm-copy-prop-iter sasm-code))) + (if (equal? cur-code new-code) + cur-code + (iter new-code (sasm-copy-prop-iter new-code))))) + +(define (sasm-deadcode-eliminate sasm-code) + (let iter ((cur-code sasm-code) + (new-code (sasm-deadcode-eliminate-iter sasm-code))) + (if (equal? cur-code new-code) + cur-code + (iter new-code (sasm-deadcode-eliminate-iter sasm-code))))) + +(define (sasm-subexp-eliminate sasm-code) + (let iter ((cur-code sasm-code) + (new-code (sasm-subexp-eliminate-iter sasm-code))) + (if (equal? cur-code new-code) + cur-code + (iter new-code (sasm-subexp-eliminate-iter new-code))))) + +(define (sasm-dataflow-optimization-pass sasm-code) + (sasm-deadcode-eliminate-iter + (sasm-copy-prop-iter + (sasm-subexp-eliminate-iter + (sasm-const-prop-iter sasm-code))))) + +(define (sasm-dataflow-optimize sasm-code) + (let ((start (current-seconds))) + (let iter ((cur-code sasm-code) + (new-code (sasm-dataflow-optimization-pass sasm-code))) + (if (or (equal? cur-code new-code) + (> (- (current-seconds) start) 60)) + cur-code + (iter new-code (sasm-dataflow-optimization-pass new-code)))))) + diff --git a/src/sasm/sasm-eval.scm b/src/sasm/sasm-eval.scm new file mode 100644 index 0000000..9b53a26 --- /dev/null +++ b/src/sasm/sasm-eval.scm @@ -0,0 +1,421 @@ +;; eval-sa.scm +;; Scheme Assembly Evaluator +;; +;; sasm-eval.scm +;; Slow, dumb explicit evaluator for SASM. Moved into the main project +;; source tree. + +;; SA Instruction Set + +;; => +;; => (| ...) +;; => (| (reg ) (const )) +;; +;; (assign (reg )) +;; (assign (const )) +;; (assign (op ) ... ) +;; (assign (label )) +;; +;; (perform (op ) ... ) +;; +;; (test (op ) ... ) +;; +;; (branch (label )) +;; (branch-true (label )) +;; (branch-false (label )) +;; (branch-zero (label ) ) +;; (branch-nonzero (label ) ) +;; +;; (goto (label )) +;; (goto (reg )) +;; +;; (save ) +;; (save (reg )) +;; +;; (restore ) + +(define (eval-sa controller return-register) + (let ((machine (eval-sa-iter controller controller (make-machine)))) + (machine-read-reg machine return-register))) + +(define (eval-sa-iter controller pc machine) + (define (continue) + (eval-sa-iter controller (cdr pc) machine)) + (define (code) (car pc)) + (define (instruction) (car (code))) + (define (continue-after proc) + (lambda (controller pc machine) + (proc (car pc) machine) + (continue))) + (define (continue-with proc) + (lambda (controller pc machine) + (eval-sa-iter controller + (proc controller pc machine) + machine))) + (define (evaluator insn) + (case insn + ((return) (continue-with eval-return)) + ((label) (continue-after (lambda (x y) #t))) + ((assign) (continue-after eval-assign)) + ((perform) (continue-with eval-perform)) + ((test) (continue-after eval-test)) + ((save) (continue-after eval-save)) + ((restore) (continue-after eval-restore)) + ((push) (continue-after eval-push)) + ((pop) (continue-after eval-pop)) + ((branch branch-true) (continue-with eval-branch)) + ((branch-false) (continue-with eval-branch-false)) + ((branch-zero) (continue-with eval-branch-zero)) + ((branch-nonzero) (continue-with eval-branch-nonzero)) + ((goto) (continue-with eval-goto)))) + (cond + ((null? pc) + machine) + ((symbol? (car pc)) + (continue)) + (else + ((evaluator (instruction)) controller pc machine)))) + +(define (eval-machine-iter controller machine) + (define print-trace? + (let ((env (getenv "SASM_INTERP_TRACE"))) + (lambda () (not (not env))))) + (define (continue) + (machine-write-reg machine 'pc (cdr (code))) + (next)) + (define (code) (machine-read-reg machine 'pc)) + (define (instruction) (car (code))) + (define (continue-after proc) + (lambda (controller pc machine) + (proc (car pc) machine) + (continue))) + (define (continue-with proc) + (lambda (controller pc machine) + (machine-write-reg machine 'pc (proc controller pc machine)) + (next))) + (define (evaluator insn) + (case (car insn) + ((return) (continue-with eval-return)) + ((label info) (continue-after (lambda (x y) #t))) + ((assign) (continue-after eval-assign)) + ((perform) (continue-with eval-perform)) + ((test) (continue-after eval-test)) + ((save) (continue-after eval-save)) + ((restore) (continue-after eval-restore)) + ((push) (continue-after eval-push)) + ((pop) (continue-after eval-pop)) + ((branch branch-true) (continue-with eval-branch)) + ((branch-false) (continue-with eval-branch-false)) + ((branch-zero) (continue-with eval-branch-zero)) + ((branch-nonzero) (continue-with eval-branch-nonzero)) + ((goto) (continue-with eval-goto)))) + (define (next) + (let ((pc (machine-read-reg machine 'pc))) + (if (and (print-trace?) + (not (null? pc))) + (begin (display ">> " ) (display (car pc)) (newline) + )) + (cond + ((null? pc) + machine) + ((symbol? (car pc)) + (continue)) + (else + ((evaluator (instruction)) controller pc machine))))) + (next)) + +(define (eval-machine-step controller machine) + (define print-trace? + (let ((env (getenv "SASM_INTERP_TRACE"))) + (lambda () (not (not env))))) + (define (continue) + (machine-write-reg machine 'pc (cdr (code))) +; (next) + ) + (define (code) (machine-read-reg machine 'pc)) + (define (instruction) (car (code))) + (define (continue-after proc) + (lambda (controller pc machine) + (proc (car pc) machine) + (continue))) + (define (continue-with proc) + (lambda (controller pc machine) + (machine-write-reg machine 'pc (proc controller pc machine)) +; (next) + )) + (define (evaluator insn) + (case (car insn) + ((return) (continue-with eval-return)) + ((label info) (continue-after (lambda (x y) #t))) + ((assign) (continue-after eval-assign)) + ((perform) (continue-with eval-perform)) + ((test) (continue-after eval-test)) + ((save) (continue-after eval-save)) + ((restore) (continue-after eval-restore)) + ((push) (continue-after eval-push)) + ((pop) (continue-after eval-pop)) + ((branch branch-true) (continue-with eval-branch)) + ((branch-false) (continue-with eval-branch-false)) + ((branch-zero) (continue-with eval-branch-zero)) + ((branch-nonzero) (continue-with eval-branch-nonzero)) + ((goto) (continue-with eval-goto)))) + (define (next) + (let ((pc (machine-read-reg machine 'pc))) + (if (and (print-trace?) + (not (null? pc))) + (begin (display ">> " ) (display (car pc)) (newline) + )) + (cond + ((null? pc) + machine) + ((symbol? (car pc)) + (continue) + (next)) + (else + ((evaluator (instruction)) controller pc machine))))) + (next)) + +(define (eval-return controller current-pc machine) + (let ((code (car current-pc)) + (return-address (machine-pop-arg machine))) + (if (not (machine-valid-return-address? return-address)) + (error "Invalid return address -- eval-return" return-address) + (let ((previous-context (machine-return-address-context return-address)) + (previous-pc (machine-return-address-pc return-address))) + (machine-write-reg machine 'pc previous-pc) + (machine2-set-current-call-context machine previous-context) + (cond ((equal? code '(return)) + #f) + ((= 2 (length code)) + (let ((n (eval-input-exp (list-ref code 1) machine))) + (let loop ((i n)) + (if (not (zero? i)) + (begin (machine-pop-arg machine) + (loop (- i 1))))) + #f)) + (else + (error "Invalid return instruction"))) + previous-pc)))) + +(define (eval-assign code machine) + (cond ((or (symbol? (cadr code)) + (and (list? (cadr code)) + (or (equal? 'sys (list-ref (cadr code) 0)) + (equal? 'reg (list-ref (cadr code) 0))))) + (machine-write-reg + machine + (if (symbol? (cadr code)) + (cadr code) + (list-ref (cadr code) 1)) + (eval-assign-exp (cddr code) machine))) + ((equal? 'arg (list-ref (cadr code) 0)) + (machine-set-arg + machine + (list-ref (cadr code) 1) + (eval-assign-exp (cddr code) machine))) + ((equal? 'local (list-ref (cadr code) 0)) + (machine-set-local + machine + (list-ref (cadr code) 1) + (eval-assign-exp (cddr code) machine))) + ((equal? 'temp (list-ref (cadr code) 0)) + (machine-set-temp + machine + (list-ref (cadr code) 1) + (eval-assign-exp (cddr code) machine))) + (else + (error "Invalid assign statement -- eval-assign" code)))) + +(define (eval-input-exp code machine) + (case (car code) + ((reg) (machine-read-reg machine (cadr code))) + ((sys) (machine-read-reg machine (cadr code))) + ((temp) (machine-get-temp machine (cadr code))) + ((arg) (machine-get-arg machine (cadr code))) + ((local) (machine-get-local machine (cadr code))) + ((const) (cadr code)) + ((label) (cadr code)) + ((result) (eval-assign-exp (cdr code) machine)) + ((symconst) (machine-lookup-symconst machine (cadr code))) + (else (error "Unknown input expression -- EVAL-INPUT-EXP" code machine)))) + +(define (eval-assign-exp code machine) + (let ((input (car code))) + (if (eqv? 'op (car input)) + (perform-operation (cadr input) + (map (lambda (c) (eval-input-exp c machine)) + (cdr code)) + machine) + (eval-input-exp input machine)))) + +(define (eval-perform controller pc machine) + (let* ((code (car pc)) + (operation (nested-list-ref code 1 1)) + (operands (cddr code))) + (perform-operation operation + (map (lambda (c) (eval-input-exp c machine)) + operands) + machine) + (case operation + ((call this-call tail-call) + (machine-read-reg machine 'pc)) + (else + (cdr pc))))) + +(define *user-defined-operation-implementations* '()) + +(define (install-operation name impl) + (cond ((assoc name *user-defined-operation-implementations*) + => + (lambda (p) (set-cdr! p impl))) + (else (set! *user-defined-operation-implementations* + (cons (cons name impl) + *user-defined-operation-implementations*))))) + +(define (operation-implementation operation-name) + (case operation-name + ((+) +) + ((*) *) + ((-) -) + ((/) /) + ((remainder) remainder) + ((quotient) quotient) + ((modulo) modulo) + ((expt) expt) + ((sin) sin) + ((cos) cos) + ((tan) tan) + ((asin) sin) + ((acos) acos) + ((atan) (lambda (a) (atan a))) + ((abs) abs) + ((=) =) + ((<) <) + ((>) >) + ((<=) <=) + ((>=) >=) + ((average) (lambda (a b) (/ (+ a b) 2))) + ((square) (lambda (x) (* x x))) + (else + (cond ((assoc operation-name *user-defined-operation-implementations*) + => + (lambda (p) (cdr p))) + (else (error "Unable to perform operation " operation-name) + #f))))) + +(define (perform-operation operation-name args machine) + (apply (operation-implementation operation-name) + args)) + +(define (eval-test code machine) + (let ((val (eval-assign-exp (cdr code) machine))) + (machine-write-flag machine val))) + +(define (eval-save code machine) + (let ((reg (let ((reg (list-ref code 1))) + (if (and (pair? reg) (eqv? 'reg (car reg))) + (cadr reg) + reg)))) + (machine-push machine (machine-read-reg machine reg)))) + +(define (eval-push code machine) + (let ((reg (list-ref code 1))) + (machine-push-arg machine (eval-input-exp reg machine)))) + +(define (eval-pop code machine) + (let ((operand (list-ref code 1))) + (cond ((equal? 'const (car operand)) + (let ((n (eval-input-exp (list-ref code 1) machine))) + (let loop ((i n)) + (if (not (zero? i)) + (begin (machine-pop-arg machine) + (loop (- i 1))))))) + ((member (car operand) '(sys reg)) + (let ((value (machine-pop-arg machine))) + (machine-write-reg machine (cadr operand) value))) + (else (error "invalid pop instruction -- eval-pop" code))))) + +(define (nested-list-ref list n . args) + (define (iter l nl) + (if (null? nl) + l + (iter (list-ref l (car nl)) (cdr nl)))) + (iter list (cons n args))) + +(define (eval-restore code machine) + (let ((reg (let ((reg (list-ref code 1))) + (if (and (pair? reg) (eqv? 'reg (car reg))) + (cadr reg) + reg)))) + (machine-write-reg + machine + reg + (machine-pop machine)))) + +(define (eval-branch-with-flag controller pc machine flag) + (let* ((code (car pc)) + (label (nested-list-ref code 1 1))) + (cond ((eqv? flag 1) + (let ((res (member (list 'label label) controller))) + (if (not res) + (error "EVAL-BRANCH: Unable to go to non-existent label " label)) + res)) + ((eqv? flag 0) + (cdr pc)) + (else + (machine-dump-state machine) + (error "EVAL-BRANCH: Invalid value for flag register " flag))))) + +(define (eval-branch controller pc machine) + (eval-branch-with-flag controller pc machine (machine-read-flag machine))) + +(define (eval-branch-false controller pc machine) + (eval-branch-with-flag controller + pc + machine + (let ((flag (machine-read-flag machine))) + (cond ((eqv? flag 1) 0) + ((eqv? flag 0) 1) + (else (error "EVAL-BRANCH-FALSE: Invalid value for flag register " flag)))))) + +(define (eval-branch-zero controller pc machine) + (let* ((insn (car pc)) + (result (eval-input-exp (list-ref insn 2) machine))) + ;; (display ";; eval-branch-zero ") + ;; (display insn) + ;; (display "; ") + ;; (display result) + ;; (newline) + (if (not (number? result)) + (begin (machine-dump-state machine) + (error "Invalid result in eval-branch-zero " (car pc) result))) + (eval-branch-with-flag controller + pc + machine + (if (zero? result) 1 0)))) + +(define (eval-branch-nonzero controller pc machine) + (let* ((insn (car pc)) + (result (eval-input-exp (list-ref insn 2) machine))) + ;; (display ";; eval-branch-zero ") + ;; (display insn) + ;; (display "; ") + ;; (display result) + ;; (newline) + (if (not (number? result)) + (error "Invalid result in eval-branch-nonzero " insn result)) + (eval-branch-with-flag controller + pc + machine + (if (zero? result) 0 1)))) + +(define (eval-goto controller pc machine) + (let* ((code (car pc)) + (label (eval-input-exp (cadr code) machine))) +; (display "EVAL-GOTO: ") (display label) (newline) + (let ((res (member (list 'label label) controller))) + (if (not res) + (begin (machine-dump-state machine) + (error "EVAL-GOTO: Unable to go to non-existent label " label))) + res))) + diff --git a/src/sasm/sasm-insel.scm b/src/sasm/sasm-insel.scm new file mode 100644 index 0000000..41deb64 --- /dev/null +++ b/src/sasm/sasm-insel.scm @@ -0,0 +1,205 @@ +;; sasm-insel.scm +;; Instruction selection module + +(need sasm/sasm-dataflow) +(need sasm/sasm-tx) + +(define (sasm-temp-generator sasm-code) + (let ((temp-max (sasm-temp-max sasm-code))) + (lambda () + (set! temp-max (+ temp-max 1)) + temp-max))) + +;; TODO OPTIMIZE +(define (sasm-insel sasm-code) + (let ((liveness (sasm-liveness-compute sasm-code)) + (tempgen (sasm-temp-generator sasm-code))) + (accum append + '() + (map (lambda (x y z) (sasm-insel-single x y z tempgen)) + sasm-code + (list-ref liveness 0) + (list-ref liveness 1))))) + +(define *last-insn* '()) +(define (sasm-attempt-match-insn insn) + (let loop ((machine-spec *machine-instructions*)) + (if (null? machine-spec) + #f + (let ((pattern (car machine-spec))) + (set! *last-insn* insn) + (let ((match (pattern-match (car pattern) insn))) + (or (and match + (cons match pattern)) + (loop (cdr machine-spec)))))))) + +(define (sasm-match-insn insn) + (if (sasm-directive? insn) + (error "sasm-match-insn called with directive")) + (or (sasm-attempt-match-insn insn) + (error "Unable to match instruction -- sasm-match-insn" insn))) + +(define (sasm-directive? insn) + (or (and (list? insn) + (equal? 'info (car insn))) + (pattern-match '(assign (? reg) (op side-effect)) + insn) + (pattern-match '(perform (op use-garbage) (? reg)) + insn))) +; (and (equal? 'perform (car insn)) +; (equal? '(op use-garbage) (list-ref insn 1))))) + +; Some notes on instruction-selection rewrite-rules: +; +; Normal instruction, no side effects or rewrite rule +; +; - No automatic save/restore functionality is needed +; +; If the instruction has side effects but no rewrite-rule: +; +; - if the SE register is live-out and not modified by the current +; instruction, save the register before and modify it after +; +; - what about live-in? The rewrite rule must be written carefully +; to introduce temporaries properly +; +; If the instruction has side effects and rewrite-rule: +; +; - if the SE register is live-in to the original instruction, save +; it before the rewrite-rule result and restore it after the +; rewrite-rule result + + +(define (sasm-insel-single insn live-in live-out tempgen) + (define (map-side-effects side-effects) + (if (null? side-effects) + '() + (append (list `(assign ,(car side-effects) (op side-effect)) + `(perform (op use-garbage) ,(car side-effects))) + (map-side-effects (cdr side-effects))))) + (define (save-live-side-effect-regs insns side-effects live-in live-out) +; (println "saving live side-effect-registers: \t\n [" insns "] \t\n[" live-in "] [" live-out "] \t\n[" side-effects "]\n\n") + (cond ((null? side-effects) + insns) + ((and (member (car side-effects) live-in) + (member (car side-effects) live-out)) + (let ((temp `(temp ,(tempgen)))) + (save-live-side-effect-regs + (append (list `(assign ,temp ,(car side-effects))) + insns + (list `(assign ,(car side-effects) ,temp))) + (cdr side-effects) + live-in + live-out))) + (else (save-live-side-effect-regs insns (cdr side-effects) live-in live-out)))) + (define (rewrite-insn insn-pat match rewrite-spec) + (if (not rewrite-spec) + (list (pattern-match-replace insn-pat match)) + (let ((temps '())) + (define (get-temp name) + (let ((entry (assoc name temps))) + (if entry + `(temp ,(cdr entry)) + (begin (set! temps (cons (cons name (tempgen)) temps)) + `(temp ,(cdar temps)))))) + (define (fix-statement stmt) + (define (fix-element exp) + (if (not (pair? exp)) + exp + (case (car exp) + ((replace) (cdr (assoc (cadr exp) match))) + ((replace-temp) (get-temp (cadr exp))) + ((result) (fix-statement exp)) + (else (if (pair? exp) + (cons (fix-element (car exp)) + (fix-element (cdr exp)))))))) + (map fix-element stmt)) + (filter (lambda (x) (not (pattern-match '(assign (? reg) (? reg)) x))) + (map fix-statement rewrite-spec))))) + (define (write-insns insn-pat match side-effects rewrite-spec live-in live-out) + (let* ((insns (rewrite-insn insn-pat match rewrite-spec)) + (filtered-se (filter-side-effects (list (pattern-match-replace insn-pat match)) + (reverse-map-side-effects side-effects) + live-in + live-out))) + (let ((se-insns + (append insns + (map-side-effects filtered-se)))) + (save-live-side-effect-regs se-insns + filtered-se + live-in + live-out)))) + (define (filter-side-effects stmts side-effects live-in live-out) + (let ((result + (subtract-lists equal? + side-effects + (accum append '() (map sasm-liveness-statement-kills stmts))))) +; (println "filter-side-effects [" stmts "]\n\t[" result "]") + result)) + (define (matchrec match insn-pat side-effects rewrite-spec result live-in live-out) + (cond ((null? match) + (write-insns insn-pat result side-effects rewrite-spec live-in live-out)) + ((and (list? (cdr (car match))) + (or (equal? 'result (car (cdr (car match)))) + (equal? 'label (car (cdr (car match)))) + (equal? 'const (car (cdr (car match)))))) + (let* ((entry (car match)) + (result-exp (if (equal? 'result (car (cdr entry))) + (cdr entry) + (list 'foobar (cdr entry)))) + (temp (tempgen)) + (new-sub-insn `(assign (temp ,temp) ,@(cdr result-exp))) + (new-temp `(temp ,temp)) + (new-match (cons (car entry) new-temp))) + ;; (println "Matching subins " new-sub-insn "; ") + ;; (begin (display "matchrec-foo") + ;; (newline) + ;; (display "insn: ") (write insn) + ;; (newline) + ;; (display "match: ") (write match) + ;; (newline) + ;; (display "new-sub-insn: ") (write new-sub-insn) + ;; (newline) + ;; (display "entry: ") (write entry) + ;; (newline) + ;; (display "insns-pat: ") (write insn-pat) + ;; (newline) + ;; (display "result: ") (write result) + ;; (newline) + ;; (display "side-effects: ") (write side-effects) + ;; (newline) + ;; (display "rewrite-spec: ") (write rewrite-spec) + ;; (newline) + ;; (display "live-in: ") (write live-in) + ;; (newline) + ;; (display "live-out: ") (write live-out) + ;; (newline) + ;; (newline)) + (append (sasm-insel-single new-sub-insn + live-in + (remove-duplicates equal? + (cons new-temp (append live-in live-out))) + tempgen) + (matchrec (cdr match) insn-pat side-effects rewrite-spec (cons new-match result) (cons new-temp live-in) live-out)))) + (else (matchrec (cdr match) insn-pat side-effects rewrite-spec (cons (car match) result) live-in live-out)))) + (define (rewrite-simple-result-assignment insn) + (if (and (equal? 'assign (car insn)) + (= 3 (length insn)) + (equal? 'result (car (list-ref insn 2)))) + `(assign ,(list-ref insn 1) ,@(cdr (list-ref insn 2))) + insn)) +; (println "Insel-Single: " insn) + (cond ((sasm-directive? insn) + (list insn)) + ((sasm-directive? (rewrite-simple-result-assignment insn)) + (list (rewrite-simple-result-assignment insn))) + (else + (let ((match-spec (sasm-match-insn (rewrite-simple-result-assignment insn)))) + (and match-spec + (matchrec (car match-spec) + (list-ref match-spec 1) + (list-ref match-spec 3) + (list-ref match-spec 4) + '() + live-in + live-out)))))) diff --git a/src/sasm/sasm-insn.scm b/src/sasm/sasm-insn.scm new file mode 100644 index 0000000..663c375 --- /dev/null +++ b/src/sasm/sasm-insn.scm @@ -0,0 +1,310 @@ +;; sasm-insn.scm +;; +;; Routines for manipulating SASM instruction sequences. + +(need scheme/tag) +(need pat/pat) + +;; instruction sequences ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (insn-seq needs modifies insns) + (tag 'insns (list needs modifies insns))) + +(define (insn-seq:needed insns) + (list-ref (safe-contents 'insns insns) 0)) + +(define (insn-seq:modified insns) + (list-ref (safe-contents 'insns insns) 1)) + +(define (insn-seq:insns insns) + (list-ref (safe-contents 'insns insns) 2)) + +(define (insn-seq:needs? insns reg) + (memq reg (insn-seq:needed insns))) + +(define (insn-seq:modifies? insns reg) + (memq reg (insn-seq:modified insns))) + +(define (empty-insn-seq) + (insn-seq '() '() '())) + +;; Labels and tokens ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define make-label-token + (let ((serial 0)) + (lambda args + (if (null? args) + (set! serial (+ serial 1))) + serial))) + +(define (make-label tag token) + (string->symbol (string-append (symbol->string tag) "-" (number->string token)))) + +(define make-temp-token + (let ((serial 0)) + (lambda () + (set! serial (+ serial 1)) + serial))) + +(define (make-temp tag token) + (list 'temp token)) + +;; basic linkage routines ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (link-goto label) + (tag ' label)) + +(define (goto-linkage-target linkage) + (safe-contents ' linkage)) + +(define (link-return number-of-args) + (tag ' (cons 'return number-of-args))) + +(define (link-next) + (tag ' 'next)) + +(define (goto-linkage label) + (link-goto label)) + +(define (return-linkage n) + (link-return n)) + +(define (next-linkage) + (link-next)) + +(define (expression-linkage) + (tag ' (vector #f))) + +(define (linkage-return? linkage-obj) + (and (tagged? ' linkage-obj) + (let ((linkage (safe-contents ' linkage-obj))) + (and (pair? linkage) + (eqv? 'return (car linkage)) + (number? (cdr linkage)))))) + +(define (linkage-goto? linkage-obj) + (and (tagged? ' linkage-obj) + (let ((linkage (safe-contents ' linkage-obj))) + (and (symbol? linkage) + (not (pair? linkage)) + (not (eqv? 'return linkage)) + (not (eqv? 'next linkage)))))) + +(define (linkage-next? linkage) + (and (tagged? ' linkage) + (eqv? 'next (safe-contents ' linkage)))) + +(define (expression-linkage? linkage) + (and (tagged? ' linkage) + (let ((linkage (safe-contents ' linkage))) + (vector? linkage)))) + +;; targets ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (expression-linkage-target linkage) + (vector-ref (safe-contents ' linkage) 0)) + +(define (register-target reg) + (tag ' `(reg ,reg))) + +(define (make-target target) + (tag ' target)) + +(define (targets-equal? target-a target-b) + (equal? (safe-contents ' target-a) + (safe-contents ' target-b))) + +(define (null-target) + (tag ' 'null)) + +(define (null-target? target) + (eqv? 'null (safe-contents ' target))) + +(define (immediate-target) + (tag ' 'imm)) + +(define (immediate-target? target) + (eqv? 'imm (safe-contents ' target))) + +(define (exp-target-register? target) + (pattern-match '(reg (? x)) (safe-contents ' target))) + +(define (exp-target-register target-obj) + (let ((target (safe-contents ' target-obj))) + (if (exp-target-register? target-obj) + (list-ref target 1) + #f))) + +(define (exp-target-is-specified-register? target register) + (and (exp-target-register? target) + (eqv? register (exp-target-register target)))) + +(define (exp-target-registers-used target) + (if (exp-target-register? target) + (list (exp-target-register target)) + '())) + +(define (exp-target-registers-modified target) + (if (exp-target-register? target) + (list (exp-target-register target)) + '())) + +(define (exp-assign-target target) + (if (null-target? target) + (error "assignment to null target -- exp-assign-target")) + (safe-contents ' target)) + +;; instruction sequence combination ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (append-insn-seq . seqs) + (define (append2 seq1 seq2) + (insn-seq (union-lists eqv? + (insn-seq:needed seq1) + (subtract-lists eqv? + (insn-seq:needed seq2) + (insn-seq:modified seq1))) + (union-lists eqv? + (insn-seq:modified seq1) + (insn-seq:modified seq2)) + (append (insn-seq:insns seq1) + (insn-seq:insns seq2)))) + (define (append-seqs seqs) + (if (null? seqs) + (empty-insn-seq) + (append2 (car seqs) + (append-seqs (cdr seqs))))) + (append-seqs seqs)) + +;; Used to append sequences where seq1 may "stomp on" registers +;; that have been initialized before seq1, and used by seq2. +;; +(define (preserving regs seq1 seq2) + (if (null? regs) + (append-insn-seq seq1 seq2) + (let ((first-reg (car regs))) + (if (and (insn-seq:needs? seq2 first-reg) + (insn-seq:modifies? seq1 first-reg)) + (preserving (cdr regs) + (insn-seq (union-lists eqv? (list first-reg) (insn-seq:needed seq1)) + (subtract-lists eqv? (insn-seq:modified seq1) (list first-reg)) + (append `((save (reg ,first-reg))) + (insn-seq:insns seq1) + `((restore (reg ,first-reg))))) + seq2) + (preserving (cdr regs) seq1 seq2))))) + +(define (preserving-loop-body regs body predicate) + (if (null? regs) + body + (let ((first-reg (car regs))) + (if (and (or (insn-seq:needs? predicate first-reg) + (insn-seq:needs? body first-reg)) + (insn-seq:modifies? body first-reg)) + (preserving-loop-body (cdr regs) + (insn-seq (insn-seq:needed body) + (subtract-lists eqv? (insn-seq:modified body) (list first-reg)) + (append `((save (reg ,first-reg))) + (insn-seq:insns body) + `((restore (reg ,first-reg))))) + predicate) + (preserving-loop-body (cdr regs) body predicate))))) + +(define (preserving-self regs seq) + (if (null? regs) + seq + (let ((first-reg (car regs))) + (if (and (insn-seq:needs? seq first-reg) + (insn-seq:modifies? seq first-reg)) + (preserving-self (cdr regs) + (insn-seq (insn-seq:needed seq) + (subtract-lists eqv? (insn-seq:modified seq) (list first-reg)) + (append `((save (reg ,first-reg))) + (insn-seq:insns seq) + `((restore (reg ,first-reg)))))) + (preserving-self (cdr regs) seq))))) + +;; Used to append two instruction sequences that are not related; +;; seq1 and seq2 are next to each other lexically in the assembly +;; code but not related at all by sequential execution. An example +;; of this is when seq2 is the body of a lambda expression, and +;; goto expressions surround it. +;; +(define (tack-insn-seq seq1 seq2) + (insn-seq + (insn-seq:needed seq1) + (insn-seq:modified seq2) + (append (insn-seq:insns seq1) (insn-seq:insns seq2)))) + +;; Used when there is a branch, i.e. an 'if' statement +;; +(define (parallel-insn-seq seq1 seq2) + (insn-seq + (union-lists eqv? (insn-seq:needed seq1) (insn-seq:needed seq2)) + (union-lists eqv? (insn-seq:modified seq1) (insn-seq:modified seq2)) + (append (insn-seq:insns seq1) (insn-seq:insns seq2)))) + +;; basic code generation ;; + +(define (codegen-linkage linkage-obj) + (let ((linkage (safe-contents ' linkage-obj))) + (cond +; ((eqv? 'return linkage) +; (insn-seq '() '() '((return)))) + ((linkage-return? linkage-obj) + (insn-seq '() '() `((perform (op pop-frame)) + (return (const ,(cdr linkage)))))) + ((linkage-next? linkage-obj) + (empty-insn-seq)) + ((linkage-goto? linkage-obj) + (insn-seq '() '() `((goto (label ,linkage))))) + (else + (error "Bad linkage specifier " linkage))))) + +(define (with-linkage insns linkage) + (preserving '() + insns + (codegen-linkage linkage))) + +(define (display-insn-seq insn-seq) + (define (display-spaced x) (display " ") (display x)) + (if (not (null? (insn-seq:needed insn-seq))) + (begin (display ";; Needs :") + (for-each display-spaced (insn-seq:needed insn-seq)) + (newline) )) + (if (not (null? (insn-seq:modified insn-seq))) + (begin (display ";; Modifies:") + (for-each display-spaced (insn-seq:modified insn-seq)) + (newline) )) + (for-each (lambda (x) (display x) (newline)) + (insn-seq:insns insn-seq))) + +(define (with-expression-linkage insns requested-target given-target linkage-obj) + (if (not (and (tagged? ' requested-target) + (tagged? ' given-target))) + (error "invalid target types -- with-expression-linkage")) + (if (and (not (expression-linkage? linkage-obj)) + (null-target? requested-target)) + (error "implicit target with expression linkage -- with-expression-linkage")) + (if (null-target? given-target) + (error "null given-target -- with-expression-linkage")) + (if (expression-linkage? linkage-obj) + (begin (if (not (or (null-target? requested-target) + (targets-equal? requested-target given-target))) + (error "expression linkage with mismatched targets -- with-expression-linkage")) + (if (vector-ref (safe-contents ' linkage-obj) 0) + (error "linkage object is being re-used -- with-expression-linkage")) + (vector-set! (safe-contents ' linkage-obj) 0 given-target) + insns) + (append-insn-seq insns + (if (targets-equal? given-target requested-target) + (empty-insn-seq) + (insn-seq (exp-target-registers-used given-target) + (exp-target-registers-modified requested-target) + `((assign ,(exp-assign-target requested-target) + ,(exp-assign-target given-target)))) ) + (codegen-linkage linkage-obj)))) + +(define (label-insn-seq label) + (insn-seq '() '() + `((label ,label)))) + diff --git a/src/sasm/sasm-interp-spec.scm b/src/sasm/sasm-interp-spec.scm new file mode 100644 index 0000000..6456dbf --- /dev/null +++ b/src/sasm/sasm-interp-spec.scm @@ -0,0 +1,43 @@ +(define *sasm-register-mapping* + '((accum . accum) + (operand . operand) + (this . this) + (index . index))) + +(define *sasm-sys-register-mapping* + '((stack-pointer . #f) + (frame-pointer . #f))) + +(define *sasm-caller-destroy-registers* + '(this index operand)) + +(define (sasm-interp-specialize! target) + (case target + ((x86) + (set! *sasm-register-mapping* + (map (lambda (x) (cons (car x) (string->symbol (cdr x)))) + nasm-x86-registers)) + (set! *sasm-sys-register-mapping* + (map (lambda (x) (cons (car x) (string->symbol (cdr x)))) + nasm-x86-sys-registers)) + (set! *sasm-caller-destroy-registers* + '(ebx ecx edx edi esi))) + ((mips) + (set! *sasm-register-mapping* + (map (lambda (x) (cons (car x) (string->symbol (cdr x)))) + sasm-mips-registers)) + (set! *sasm-sys-register-mapping* + (map (lambda (x) (cons (car x) (string->symbol (cdr x)))) + sasm-mips-sys-registers)) + (set! *sasm-caller-destroy-registers* + '($t1 $t2 $t3 $v0 $v1 $a0 $a1 $a2 $a3 $a4 + $t4 $t5 $t6 $t7 $s0 $s1 $s2 $s3 $s4 + $s5 $s6 $s7 $t8))) + (else + (error "unknown target -- sasm-interp-specialize")))) + +(define (sasm-interp-spec-register name) + (cdr (assoc name *sasm-register-mapping*))) + +(define (sasm-interp-spec-sys-register name) + (cdr (assoc name *sasm-sys-register-mapping*))) diff --git a/src/sasm/sasm-interp.scm b/src/sasm/sasm-interp.scm new file mode 100644 index 0000000..156d7d6 --- /dev/null +++ b/src/sasm/sasm-interp.scm @@ -0,0 +1,1033 @@ +;; sasm-interp.scm +;; +;; This module implements the sasm interpreter, interfacing to the +;; sasm machine simulator and sasm language evaluator. + +(need util/list) +(need util/string) +(need sasm/sasm-machine) +(need sasm/sasm-eval) +(need sasm/sasm-interp-spec) +(need sasm/sasm-tx) +(need sasm/tx/interp) +(need sasm/sasm-ast) +(need sasm/sasm-visitor) +(need sasm/sasm-analyze) +(need sasm/sasm-parse) +(need sasm/sasm-rewrite) +(need util/filesystem) + +(define *sasm-interp-output-port* #f) +(define (sasm-interp-output-port) + (if *sasm-interp-output-port* + *sasm-interp-output-port* + (current-output-port))) + +(define *sasm-interp-input-port* #f) +(define (sasm-interp-input-port) + (if *sasm-interp-input-port* + *sasm-interp-input-port* + (current-input-port))) + +(define *sasm-interp-print-timings* #f) + +(define (sasm-interp-make-machine) + (let ((machine (make-machine2))) + (let ((stack (sasm-interp-spec-sys-register 'stack-pointer)) + (frame (sasm-interp-spec-sys-register 'frame-pointer))) + (if (and stack frame) + (machine2-set-sys-registers! machine stack frame))) + machine)) + +(define *machine* (sasm-interp-make-machine)) +(define *memory* '()) +(define *controller* '()) +(define *main-entry* #f) +(define *debug-mode* #f) + +(define (sasm-interp-module-context file-name) + (let ((controller '()) + (memory '())) + (define (get-file) + file-name) + (define (get-memory) + memory) + (define (append-memory x) + (set! memory (cons x memory))) + (define (get-controller) + controller) + (define (append-controller x) + (set! controller (append controller (list x)))) + (lambda (x . args) + (apply + (case x + ((get-memory) get-memory) + ((append-memory) append-memory) + ((get-controller) get-controller) + ((append-controller) append-controller) + ((get-file) get-file) + (else #f)) + args)))) + +(define (sasm-interp-symbolic-pointer? obj) + (or (symbol? obj) + (and (pair? obj) (symbol? (car obj)) (integer? (cdr obj))))) + +(define (sasm-interp-symbolic-pointer-key obj) + (if (symbol? obj) + obj + (car obj))) + +(define (sasm-interp-symbolic-pointer-offset obj) + (if (symbol? obj) + 0 + (cdr obj))) + +(define (sasm-interp-add-pointer x y) + (cond ((or (symbol? y) (pair? y)) + (add-pointer y x)) + ((symbol? x) + (if (not (integer? y)) + (error "add-pointer: unable to add symbolic pointers" x y)) + (cons x y)) + ((and (pair? x) (symbol? (car x)) (integer? (cdr x))) + (if (not (integer? y)) + (error "add-pointer: unable to add symbolic pointers" x y)) + (cons (car x) (+ (cdr x) y))) + (else + (+ x y)))) + +(define (memory-add addr value) + (set! *memory* (cons (cons addr value) + *memory*))) + +(define (memory-ref-area-size addr offset) + (if (integer? addr) + 1 + (let ((entry (assoc (sasm-interp-symbolic-pointer-key addr) + *memory*))) + (cond ((not entry) + (error ";; Invalid memory address in memory-ref-area-size " + addr)) + ((vector? (cdr entry)) + (let ((outer-length (vector-length (cdr entry)))) + (- outer-length offset))) + ((and (pair? (cdr entry)) + (integer? (car (cdr entry))) + (vector? (cdr (cdr entry)))) + (let ((the-vector (cdr (cdr entry))) + (the-offset (+ (car (cdr entry)) + (sasm-interp-symbolic-pointer-offset addr) + offset))) + (- (vector-length the-vector) the-offset))) + (else + (error "Invalid memory entry " addr entry)))))) + +(define (memory-ref addr offset) + (if (integer? addr) + (begin (if (zero? addr) + (error "Dereference 0! " addr)) + (machine2-memory-ref *machine* (+ addr offset))) + (let ((entry (assoc (sasm-interp-symbolic-pointer-key addr) + *memory*))) + (cond ((not entry) + (begin (display ";; Invalid memory address: ") + (display addr) + (newline) + (machine-dump-state *machine*) + (display ";; Contents of memory: ") + (newline) + (for-each (lambda (entry) + (display ";; ") + (display entry) + (newline)) + *memory*) + (error "Invalid memory address: " addr))) + ((vector? (cdr entry)) + (let ((the-vector (cdr entry)) + (vector-offset (+ (sasm-interp-symbolic-pointer-offset addr) + offset))) + (if (and (>= vector-offset 0) (< vector-offset (vector-length the-vector))) + (vector-ref (cdr entry) vector-offset) + (begin (sasm-machine-dump) + (error "Invalid vector offset in memory-ref [vector-direct]" + addr + offset + vector-offset + the-vector))))) + ((and (pair? (cdr entry)) + (integer? (car (cdr entry))) + (vector? (cdr (cdr entry)))) + (let ((the-vector (cdr (cdr entry))) + (the-offset (+ (car (cdr entry)) + (sasm-interp-symbolic-pointer-offset addr) + offset))) + (if (and (>= the-offset 0) (< the-offset (vector-length the-vector))) + (vector-ref the-vector the-offset) + (begin (sasm-machine-dump) + (error "Invalid vector offset in memory-ref [vector-indirect]" + addr + offset + (car (cdr entry)) + (sasm-interp-symbolic-pointer-offset addr) + the-offset + the-vector))))) + (else + (error "Invalid memory entry " entry)))))) + +(define (memory-set! addr offset value) + (if (integer? addr) + (begin (if (zero? addr) + (error "write to 0! " addr)) + (machine2-memory-set! *machine* (+ addr offset) value)) + (let ((entry (assoc (sasm-interp-symbolic-pointer-key addr) + *memory*))) + (if (not entry) + (error "Invalid memory address: " addr) + (vector-set! (cdr entry) + (+ (sasm-interp-symbolic-pointer-offset addr) + offset) + value))))) + +(define (controller-add code) + (set! *controller* (append *controller* code))) + +(define (malloc size) + (make-vector size)) + +(define (store-array array index value) + (memory-set! array index value)) + +(define (load-array array index) + (memory-ref array index)) + +(define (destroy-registers machine) + (for-each (lambda (reg) + (machine-write-reg machine reg #f)) + *sasm-caller-destroy-registers*)) + +(define (sasm-interp-next-pc current-pc) + (if (null? current-pc) + current-pc + (cdr current-pc))) + +(define (call symbol) + (define (@r name) + (sasm-interp-spec-register name)) + (let ((current-pc (machine-read-reg *machine* 'pc)) + (ctx (machine2-get-current-call-context *machine*))) + (define (read-string base-pointer length) + (let ((str (make-string length))) + (let loop ((index 0)) + (if (>= index length) + str + (begin (string-set! str index (integer->char (memory-ref base-pointer + index))) + (loop (+ index 1))))))) + (define (begin-native) + (machine-push-arg *machine* (cons '$return-address ctx)) + (sasm-machine-set-call-context ctx) + (machine-push-frame *machine*) + (machine-push-locals *machine* 0)) + (define (end-native) + (machine-pop-frame *machine*) + (machine-pop-arg *machine*) + (sasm-machine-set-call-context ctx) + (machine-write-reg *machine* 'pc (sasm-interp-next-pc current-pc))) + (define (call-proc-by-name symbol) + (let ((pc (member (list 'label symbol) *controller*))) + (if (not pc) + (begin + (machine-dump-state *machine*) + (error "Attempt to call non-existent function " symbol))) + (machine-write-reg *machine* 'pc pc) + (machine-push-arg *machine* (list '$return-address ctx (sasm-interp-next-pc current-pc))) + (sasm-machine-set-call-context symbol))) + (case symbol + ((mj-malloc cp-mj-malloc) + (begin-native) + (destroy-registers *machine*) + (machine-write-reg *machine* (@r 'accum) (make-vector (machine-get-arg *machine* 0))) + (end-native)) + ((mj-system-out-println cp-mj-system-out-println) + (begin-native) + (if (integer? (machine-get-arg *machine* 0)) + (display (bit-twoscomp (machine-get-arg *machine* 0)) + (sasm-interp-output-port)) + (write (machine-get-arg *machine* 0) + (sasm-interp-output-port))) + (newline (sasm-interp-output-port)) + (destroy-registers *machine*) + (machine-write-reg *machine* (@r 'accum) (machine-get-arg *machine* 0)) + (end-native)) + ((mj-array-length cp-mj-array-length) + (begin-native) + (destroy-registers *machine*) + (machine-write-reg *machine* + (@r 'accum) + (vector-length (machine-get-arg *machine* 0))) + (end-native)) + ((scheme-rtl-get-stdout-handle) + (begin-native) + (machine-write-reg *machine* (@r 'accum) (sasm-interp-output-port)) + (end-native)) + ((scheme-rtl-get-stdin-handle) + (begin-native) + (machine-write-reg *machine* (@r 'accum) (sasm-interp-input-port)) + (end-native)) + ((scheme-rtl-open-input-file-handle) + (begin-native) + (machine-write-reg *machine* + (@r 'accum) + (open-input-file (read-string (machine-get-arg *machine* 0) + (machine-get-arg *machine* 1)))) + (end-native)) + ((scheme-rtl-close-file-handle) + (begin-native) + (let ((stream (machine-get-arg *machine* 0))) + (cond ((input-port? stream) (close-input-port stream)) + ((output-port? stream) (close-output-port stream)) + (error "Not a scheme stream"))) + (end-native)) + ((scheme-rtl-open-output-file-handle) + (begin-native) + (machine-write-reg *machine* + (@r 'accum) + (open-output-file (read-string (machine-get-arg *machine* 0) + (machine-get-arg *machine* 1)))) + (end-native)) + ((scheme-rtl-read-byte) + (begin-native) + (let ((ch (read-char (machine-get-arg *machine* 0)))) + (let ((byte (if (eof-object? ch) + -1 + (char->integer ch)))) + (machine-write-reg *machine* (@r 'accum) byte))) + (end-native)) + ((scheme-rtl-write-byte) + (begin-native) + (write-char (integer->char (machine-get-arg *machine* 0)) + (machine-get-arg *machine* 1)) + (end-native)) + ((scheme-rtl-runtime-type-error) + (println "SASM Runtime Type Error") + (begin-native) + (let* ((arg0 (machine-get-arg *machine* 0)) + (arg1 (machine-get-arg *machine* 1))) + (println " " arg0) + (println " " arg1) + (end-native)) + (sasm-machine-dump) + (sasm-debugger-repl #f)) + ((scheme-rtl-runtime-argument-count-error) + (println "SASM Argument Count Error") + (begin-native) + (let* ((arg0 (machine-get-arg *machine* 0)) + (arg1 (machine-get-arg *machine* 1))) + (println " " arg0) + (println " " arg1) + (end-native)) + (sasm-machine-dump) + (sasm-debugger-repl #f)) + (else + (call-proc-by-name symbol))) + (case symbol + ((cp-mj-malloc cp-mj-system-out-println cp-mj-array-length + cp-rtl-read-byte cp-rtl-open-input-file-handle + cp-rtl-open-output-file-handle) + (machine-pop-arg *machine*)) + ((cp-rtl-write-byte) + (machine-pop-arg *machine*) + (machine-pop-arg *machine*)) + ) + )) + +(define (tail-call symbol n-next-args n-cur-args) + (machine-pop-frame-tail-call *machine* n-next-args n-cur-args) + (let ((pc (member (list 'label symbol) *controller*))) + (if (not pc) + (error "Attempt to tail-call non-existent function " symbol)) + (machine-write-reg *machine* 'pc pc) + )) + +(define (sasm-init) + (set! *machine* (sasm-interp-make-machine)) + (machine-write-reg *machine* 'pc #f) + (set! *memory* '()) + (set! *controller* '()) + (set! *main-entry* 'sasm-main-entry) + (sasm-interp-symconst-machine-params) + (machine-write-reg *machine* 'step-count 0)) + +(define-syntax sasm-dispatch + (syntax-rules (:parent) + ((_ :parent