Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Move to old-code

svn path=/old-code/; revision=156217
  • Loading branch information...
commit 89135ee65b04565b6fe93ce1432b90b84d33aa61 1 parent 795f1c9
@migueldeicaza migueldeicaza authored
Showing with 3,659 additions and 0 deletions.
  1. +5 −0 MonoLOGO/.cvsignore
  2. +2 −0  MonoLOGO/AUTHORS
  3. +20 −0 MonoLOGO/COPYING
  4. +204 −0 MonoLOGO/ChangeLog
  5. +266 −0 MonoLOGO/ChangeLog.old
  6. +12 −0 MonoLOGO/Makefile
  7. +54 −0 MonoLOGO/Mono.Languages.Logo/Makefile
  8. +14 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/ArgumentInfo.cs
  9. +128 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/CSharpCompiler.cs
  10. +62 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Compiler.cs
  11. +37 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Element.cs
  12. +13 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/ElementType.cs
  13. +100 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Function.cs
  14. +56 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/IndentingWriter.cs
  15. +33 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/InstructionList.cs
  16. +152 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Interpreter.cs
  17. +429 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Parser.cs
  18. +11 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Token.cs
  19. +45 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/TokenList.cs
  20. +19 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/TokenType.cs
  21. +251 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Tokenizer.cs
  22. +204 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/CTSMessageTarget.cs
  23. +17 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/DefaultArgumentCountAttribute.cs
  24. +269 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/Funcs.cs
  25. +13 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/IMessageStore.cs
  26. +113 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/IMessageStoreCollection.cs
  27. +10 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/IMessageTarget.cs
  28. +13 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/ITypedMessageStore.cs
  29. +262 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/LogoBinder.cs
  30. +72 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/LogoContext.cs
  31. +48 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/LogoMessageTarget.cs
  32. +11 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/MessageInfo.cs
  33. +16 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/MessageNotSupportedException.cs
  34. +10 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/PassContextAttribute.cs
  35. +10 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/TypedMessageArgument.cs
  36. +6 −0 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/TypedMessageInfo.cs
  37. +21 −0 MonoLOGO/Mono.Languages.Logo/test/Makefile
  38. +20 −0 MonoLOGO/Mono.Languages.Logo/test/test-binder.cs
  39. +40 −0 MonoLOGO/Mono.Languages.Logo/test/test-cts.cs
  40. +95 −0 MonoLOGO/Mono.Languages.Logo/test/test-interp.cs
  41. +64 −0 MonoLOGO/Mono.Languages.Logo/test/test-parser.cs
  42. +18 −0 MonoLOGO/Mono.Languages.Logo/test/test-tokenizer.cs
  43. 0  MonoLOGO/README
  44. +60 −0 MonoLOGO/console/console-gtk.cs
  45. +43 −0 MonoLOGO/console/console.cs
  46. +20 −0 MonoLOGO/console/makefile
  47. +24 −0 MonoLOGO/console/textwriter-gtk.cs
  48. +61 −0 MonoLOGO/docs/dispatch.txt
  49. +31 −0 MonoLOGO/docs/syntax.txt
  50. +14 −0 MonoLOGO/mlogo/Makefile
  51. +67 −0 MonoLOGO/mlogo/main.cs
  52. 0  MonoLOGO/tests/empty.logo
  53. +10 −0 MonoLOGO/tests/fun.logo
  54. +15 −0 MonoLOGO/tests/function.logo
  55. +9 −0 MonoLOGO/tests/function2.logo
  56. +8 −0 MonoLOGO/tests/gtk.logo
  57. +3 −0  MonoLOGO/tests/hello.logo
  58. +5 −0 MonoLOGO/tests/infix.logo
  59. +5 −0 MonoLOGO/tests/list.logo
  60. +15 −0 MonoLOGO/tests/math.logo
  61. +5 −0 MonoLOGO/tests/output.logo
  62. +2 −0  MonoLOGO/tests/run.logo
  63. +3 −0  MonoLOGO/tests/sum.logo
  64. +6 −0 MonoLOGO/tests/varargs.logo
  65. +4 −0 MonoLOGO/tests/variables.logo
  66. +4 −0 MonoLOGO/tests/word.logo
View
5 MonoLOGO/.cvsignore
@@ -0,0 +1,5 @@
+mlogo.exe
+logolib.DLL
+logo-parser.cs
+y.output
+
View
2  MonoLOGO/AUTHORS
@@ -0,0 +1,2 @@
+Rachel Hestilow <rachel@nullenvoid.com>
+
View
20 MonoLOGO/COPYING
@@ -0,0 +1,20 @@
+Copyright (C) 2001-2003 Rachel Hestilow.
+
+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.
+
View
204 MonoLOGO/ChangeLog
@@ -0,0 +1,204 @@
+2004-01-21 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Mono.Languages.Logo.Runtime/LogoBinder.cs (Distance):
+ Check the interfaces implemented for each base type
+ as well, as Mono no longer includes inherited interfaces
+ in GetInterfaces ()
+
+ * Mono.Languages.Logo/test/*.cs: Update tests to compile.
+
+ * tests/run.logo: Add a second version of the statement that
+ does not go through Run, for comparison purposes.
+
+2003-05-15 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Mono.Langauges.Logo.Compiler/ElementType.cs: Add new
+ QuestionMark type.
+ * Mono.Languages.Logo.Compiler/Interpreter.cs: New
+ form of Execute that operates on runlists.
+ * Mono.Languages.Logo.Compiler/Parser.cs: Add new
+ AllowQuestionMark property and runlist ctor
+ which wrap around the Tokenizer equivalents. Add
+ support for QuestionMark tokens.
+ * Mono.Languages.Logo.Compiler/TokenType.cs: Add new
+ QuestionMark type.
+ * Mono.Languages.Logo.Compiler/Tokenizer.cs: Add
+ new AllowQuestionMark property and runlist ctor.
+ (TokenForChar): If AllowQuestionMark is set to true,
+ parse ? as a QuestionMark token.
+
+ * Mono.Languages.Logo.Runtime/Funcs.cs: Make ListToString
+ an internal method, as it is useful in Interpreter. Add
+ new function Run.
+
+ * tests/run.logo: Added.
+
+2003-05-11 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Mono.Languages.Logo/Makefile: Updated.
+
+ * Mono.Languages.Logo.Compiler/CSharpCompiler.cs: Added.
+ * Mono.Languages.Logo.Compiler/Compiler.cs: Added.
+ * Mono.Languages.Logo.Compiler/IndentingWriter.cs: Added.
+ * Mono.Languages.Logo.Compiler/Interpreter.cs: Update
+ for new SendMessage semantics.
+
+ * Mono.Languages.Logo.RunTime/ITypedMessageStore.cs: Added.
+ * Mono.Languages.Logo.RunTime/TypedMessageArgument.cs: Added.
+ * Mono.Languages.Logo.RunTime/TypedMessageInfo.cs: Added.
+ * Mono.Languages.Logo.Runtime/CTSMessageTarget.cs: Update
+ for new SendMessage semantics. Implement ITypedMessageStore.
+ Add a new construct-time argument to not automatically
+ wrap objects in CTSMessageTargets.
+ * Mono.Languages.Logo.Runtime/IMessageStoreCollection.cs: Update
+ for new SendMessage semantics. Implement ITypedMessageStore.
+ * Mono.Languages.Logo.Runtime/IMessageTarget.cs: Change
+ SendMessage to return the result instead of using a byref
+ argument.
+ * Mono.Languages.Logo.Runtime/LogoMessageTarget.cs: Update
+ for new SendMessage semantics.
+
+ * mlogo/main.cs: Add new /compile option.
+
+2003-05-08 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * COPYING: Update copyright.
+
+ * Mono.Languages.Logo.Compiler/Function.cs:
+ (Describe): Do not count the collector argument towards
+ the min_argc.
+ (Invoke): Support collector aruments. Set result to
+ the value returned by Interpreter.Execute.
+ * Mono.Languages.Logo.Compiler/Interpreter.cs:
+ (Execute): If the "output" statement is called, return
+ with the value passed to it.
+ * Mono.Languages.Logo.Compiler/Parser.cs: Remove
+ commented-out cruft.
+
+ * Mono.Languages.Logo.Runtime/Funcs.cs: New method
+ Output.
+ * Mono.Languages.Logo.Runtime/LogoContext.cs: New
+ properties StopExecution and OutputValue. New method
+ Output.
+ * Mono.Languages.Logo.Runtime/LogoMessageTarget.cs:
+ Make funcs a case-insensitive hash table.
+
+ * tests/function2.logo: Print out all arguments to foo,
+ and add an actual call to foo.
+
+2003-05-07 Rachel Hestilow <rachel@nullenvoid.com>
+
+ User-defined functions work! There has been far too long
+ a gap in development to write a proper ChangeLog entry.
+
+2002-12-22 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Makefile: Add clean target. Bomb out on subdir errors.
+
+ * Mono.Languages.Logo.Compiler/ElementType.cs: Add new Variable
+ type. This allows the interpreter/compiler to optimize certain
+ static-string variable accesses.
+ * Mono.Languages.Logo.Compiler/Interpreter.cs: Maintain a root
+ LogoContext.
+ (CollectArgs, Execute): Handle ElementType.Variable.
+ (ExecuteStatement): Pass context to SendMessage.
+ * Mono.Languages.Logo.Compiler/Parser.cs (ParseInfix): Handle
+ unary minus as a special case.
+ (ParseBackwards): Handle unary minus as a statement for now.
+ Handle variable accesses as ElementType.Variable.
+
+ * Mono.Languages.Logo.Runtime/PassContextAttribute.cs: Added.
+ * Mono.Languages.Logo.Runtime/IMessageTarget (SendMessage):
+ Require a LogoContext.
+ * Mono.Languages.Logo.Runtime/LogoBinder.cs: Accept a LogoContext
+ in ctor, and add a Context property. Support PassContextAttribute.
+ (BindToMethod): Allow null in object arguments (assume "object" type).
+ Fix a bug in min_vararg_count value (was always being set to 1).
+ * Mono.Languages.Logo.Runtime/CTSMessageTarget.cs:
+ (SendMessage): Remove dead signature code. Set context on binder.
+ (ListMessages): Support PassContextAttribute.
+ * Mono.Languages.Logo.Runtime/Funcs.cs: New functions Minus, Make,
+ LocalMake, Local, and Thing.
+ * Mono.Languages.Logo.Runtime/LogoContext.cs: Add a RootContext
+ property. Add a static "NullVariable" property to be used
+ when allocating variable slots.
+ * Mono.Languages.Logo/Makefile: Add PassContextAttribute.cs.
+
+ * Mono.Languages.Logo/test/test-cts.cs: Pass in a LogoContext
+ to SendMessage.
+ * Mono.Languages.Logo/test/test-tokenizer.cs: Tokenize the specified
+ file, not a hardcoded string.
+
+ * tests/math.logo: Fix a typo in unary minus. This works now,
+ except for the unimplemented *seq functions -- comment those out.
+ * tests/sum.logo: Make this print the results out.
+
+2002-12-13 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Mono.Languages.Logo.Runtime/DefaultArgumentCountAttribute.cs,
+ Funcs.cs, LogoBinder.cs, LogoContext.cs: Added.
+ * Mono.Languages.Logo/test/test-binder.cs: Added.
+ * Mono.Languages.Logo/Makefile, test/Makefile: Update sources.
+ * Mono.Lnaguages.Logo.Runtime/CTSMessageTarget.cs: Update to use
+ the new custom Binder. Move most of the logic (varargs, etc)
+ there.
+ * Mono.Languages.Logo.Runtime/IMessageStoreCollection.cs:
+ (SendMessage): Fix whitespace typo.
+ * Mono.Languages.Logo.Runtime/MessageNotSupportedException.cs:
+ Make the error string something meaningful.
+
+ * mlogo/: Added.
+ * Makefile: Add mlogo to SUBDIRS.
+
+ * tests/word.logo: Added.
+
+2002-12-09 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Mono.Languages.Logo.Compiler/Interpreter.cs (ConstructList):
+ Make this work recursively for sublist elements.
+ * Mono.Languages.Logo.Compiler/Parser.cs (ParseInfix): Fix the
+ algorithm to order consecutive operations properly.
+ * Mono.Languages.Logo/test/test-interp.cs: Implement some
+ basic LOGO functions. Fix print to use type (so lists, etc
+ get printed properly).
+
+ * tests/infix.logo: Test the order of divisions -- 1/2/4 should
+ become (1/2)/4, not 1/(2/4).
+
+2002-12-08 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Mono.Languages.Logo.Compiler/Interpreter.cs: Added.
+ * Mono.Languages.Logo.Runtime/CTSMessageTarget.cs:
+ (SendMessage): Fold in varargs arguments. Pass in null for
+ static methods.
+ (SupportsMessage): Catch AmbiguousMatchException, consider
+ it to mean the method exists.
+ * Mono.Languages.Logo.Runtime/IMessageStoreCollection.cs:
+ Implement IMessageTarget.
+ * Mono.Languages.Logo/test/test-interp.cs: Added.
+ * Mono.Languages.Logo/test/Makefile: Build test-interp.
+ * Mono.Languages.Logo/Makefile: Move "test" subdir building
+ to a seperate target.
+
+ * tests/infix.logo: Add a simple sum test.
+
+2002-12-07 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Mono.Languages.Logo.Compiler/Parser.cs:
+ (Parse): Do infix preprocessing (to convert into prefix).
+ (ParseBackwards): Handle infixes as prefixes with a set number of
+ args.
+ * Mono.Languages.Logo.Compiler/TokenList.cs:
+ (Extend): Change parameter type to ICollection.
+ (Reverse): Added.
+ * Mono.Languages.Logo.Runtime/CTSMessageTarget.cs (ListMessages):
+ Set max_argc to -1 if the method has a varargs prototype.
+ * Mono.Languages.Logo/test/test-parser.cs (Funcs): Change print
+ to be a varargs function.
+
+ * tests/infix.logo: Added.
+
+2002-11-28 Rachel Hestilow <rachel@nullenvoid.com>
+
+ * Rewrite. Massive changes.
+
View
266 MonoLOGO/ChangeLog.old
@@ -0,0 +1,266 @@
+2002-06-10 Rachel Hestilow <hestilow@ximian.com>
+
+ * block.cs: Add line length accessor, and a flush method.
+
+ * dispatch.cs: Break up LOGO lib funcs into different
+ categories.
+
+ * element.cs: Add "eval" method.
+
+ * *.cs: Implement Eval in all subclasses.
+
+ * logo-list.cs, list-element.cs: Change to new namespace.
+ Also, remove methods and add generic logo functions
+ that work on all IEnumerables.
+
+ * logo-funcs.cs: Broken up into lib-*.cs.
+ * lib-*.cs: Added.
+
+ * instruction-list.cs: Added; beginning of lambda support.
+
+ * optimizer.cs: Added.
+
+ * makefile: Move most sources into logolib (since we
+ have to parse things at runtime too)
+
+ * main.cs: Add --compile flag, compile to bytecode and run immediately
+ by default. This does not work yet. Optimize and write the
+ .exe file if --compile.
+
+ * tokenizer.cs, parser.cs: Add support for question mark parsing
+ in lambdas.
+
+ * console: New interactive console.
+
+2002-05-22 Rachel Hestilow <hestilow@ximian.com>
+
+ * block.cs: Add manipulator functions for body.
+
+ * dispatch.cs: Hack around incomplete attribute support in mono.
+ Change Delegate to instance method -- mono doesn't seem to like
+ that either.
+
+ * util.cs: Add GetMethod/GetConstructor/etc, move all code to use
+ this.
+
+ * list-element.cs: Get array type in a different way.
+
+ * logo-array.cs, logo-funcs.cs, logo-list.cs, logo-sequence.cs:
+ Change Array to object[].
+
+ * main-block.cs: Define a default constructor on our own,
+ so that we know about it.
+
+ * parser.cs, token.cs: New parser added.
+
+ * main.cs: Use the new parser.
+
+ * makefile: Use mcs by default, remove jay parser, add
+ new parser.
+
+ * tests/gtk.logo: New test.
+
+ * method.cs: Check Body != null. Use Ldsfld instead of Ldfld.
+
+ * output-element.cs: Add new default constructor, use block
+ semantics for body.
+
+2002-05-03 Rachel Hestilow <hestilow@ximian.com>
+
+ * dispatch.cs (Invoke): Only adjust length if method is
+ instance, not static.
+ (ProcessWithReturn): Do not overwrite stack; instead modify existing one.
+
+ * logo-funcs.cs: Add basic math functions.
+
+ * logo-parser.jay: Parse infix and unary operators.
+
+ * logo-tokenizer.cs: Return proper tokens for infix and unary operators.
+ Also, respect ()[] as word boundaries.
+
+ * makefile: Add infix-operator.cs.
+
+ * statement.cs, varargs-statement.cs: Add protected empty constructors.
+
+ * infix-operator.cs, tests/math.logo: Added.
+
+2002-05-01 Rachel Hestilow <hestilow@ximian.com>
+
+ * dispatch.cs: Rewrite vararg/stack/etc indexing to be more
+ accurate in all cases. Also, give more priority to overloaded functions
+ with more arguments (ie Run (void) < Run (Form) ).
+
+ * logo-funcs.cs: Add function "New".
+
+ * logo-parser.jay: Fix counting on embedded varargs statements.
+
+ * logo-stack.cs: Add functions AddAssembly & LookupType.
+ (ctor): Add default namespaces.
+
+ * logo-tokenizer.cs: Support "." as part of an identifier.
+
+ * main-block.cs: Load assemblies into root stack.
+
+ * main.cs: Add "/r" option for assemblies.
+
+ * util.cs: Load assemblies here too.
+
+ * varargs-statement: Make argc a property "Count".
+
+ * tests/winforms.logo: Added.
+
+ * makefile: compile winforms example
+
+2002-04-29 Rachel Hestilow <hestilow@ximian.com>
+
+ * block.cs: Move stack emission into scope.cs.
+
+ * dispatch.cs: Support variable argument collection.
+
+ * element.cs: Store some common stack ops/types in protected fields.
+
+ * logo-funcs.cs (Use, Sum): New functions.
+
+ * logo-parser.jay, logo-tokenizer.cs: Parse varargs expressions and
+ output statements. Also fix quote parsing problem.
+
+ * logo-stack.cs: Store namespaces.
+
+ * makefile: Add varargs-statement, output-element, scope. Alphabetize.
+
+ * method.cs: Inherit from Scope, not Block. Export return of System.Object
+ if there is an output statement.
+
+ * scope.cs, varargs-statement.cs, output-element.cs: Added.
+
+ * statement.cs: Clean up.
+
+ * tests/hello.logo: Add test for the quote-breaking problem.
+
+ * tests/varargs.logo, tests/output.logo: Added.
+
+2002-03-12 Rachel Hestilow <hestilow@ximian.com>
+
+ * logo-parser.jay: Remove all the "nointerps" and "unquoted" stuff,
+ rewrite in favor of a simple LIST_ELEMENT token.
+
+ * logo-tokenizer.cs (xToken): If within a list, lazily evaluate anything
+ other than numeric and list literals.
+
+2002-03-11 Rachel Hestilow <hestilow@ximian.com>
+
+ * logo-parser.jay: Add function parsing.
+
+ * logo-tokenizer.cs (xToken): Check for tokens "TO" and "END".
+
+ * logo-stack.cs: Add field/property class_type (used for dynamic
+ dispatch within a class).
+
+ * emit-context.cs: Add "global_stack". (needed because a field
+ is handled differently than a local).
+
+ * main-block.cs (AddFunction): Added.
+ (Emit): Emit functions, and define a global stack field.
+
+ * method.cs: Load arguments into stack's variable dictionary.
+
+ * dispatch.cs (Invoke): Check within the stack's class space for methods
+ as well.
+
+ * tests/function.logo: Added. Functions work now!
+
+2002-03-10 Rachel Hestilow <hestilow@ximian.com>
+
+ * emit-context.cs, method.cs: Added.
+
+ * main-block.cs: Derive from Method.
+
+ * element.cs (Emit): Change to simply use EmitContext.
+
+ * *.cs: Update for EmitContext.
+
+ * main.cs: Allow MainBlock to generate most of the module/etc stuff.
+
+ * dispatch.cs (CollectArgs): If there are multiple method overloads,
+ try to attach to the one with the least type distance.
+
+ * logo-funcs.cs (Print): Add list overload in preparation for
+ the big LogoList->System.Array conversion.
+
+2002-03-10 Rachel Hestilow <hestilow@ximian.com>
+
+ * dispatch.cs (Invoke, Filter): Allow option for lazily binding
+ (used for a 2-stage dispatch)
+ (Process): Convert to a 2-stage lazy-strong binding process.
+
+2002-03-09 Rachel Hestilow <hestilow@ximian.com>
+
+ * logo-stack.cs, logo-uses-stack-attribute.cs: Added.
+
+ * element.cs (Emit): Add argument use_stack, instead of just passing
+ in a null stack.
+
+ * dispatch.cs: Rewrite for semi-correct scheduling.
+
+ * logo-funcs.cs (Make, Thing): Use the stack.
+
+ * docs/*.txt: Added.
+
+2002-03-02 Rachel Hestilow <hestilow@ximian.com>
+
+ * block.cs: Remove commented-out code.
+
+ * variable-reference.cs: Added (equivalent to THING "name).
+
+ * logo-parser.jay: Generate a VariableReference for :identifer.
+
+ * logo-tokenizer.cs (xToken): Return Token.COLON_REFERENCE for ":".
+
+ * makefile (SOURCES): Add variable-reference.cs
+
+ * tests/variables.logo: Also check alternative syntax.
+
+2002-03-02 Rachel Hestilow <hestilow@ximian.com>
+
+ * dispatch.cs: Add alternate Invoke which returns values rather
+ than pushing them on the stack.
+
+ * logo-funcs.cs: Add functions Map and Foreach.
+
+ * logo-parser.jay: Adjust list_block to not interpret tokens.
+
+ * logo-tokenizer.cs: Return Token.QUOTE on ".
+
+ * statement.cs (invoke): Fully qualify method signature to lookup.
+
+2002-03-02 Rachel Hestilow <hestilow@ximian.com>
+
+ * logo-funcs.cs: Add functions _Dict, Make, and Thing (preliminary
+ variable support).
+
+ * dispatch.cs (Invoke, Filter): Make lookups case-insensitive.
+
+2002-02-26 Rachel Hestilow <hestilow@ximian.com>
+
+ * element.cs: Make class public.
+ (return_type): Initialize to null.
+ (CollectArgs): Remove.
+ (Emit): Add stack argument.
+ (PushResult): Added.
+
+ * list-element.cs:
+ * literal-element.cs:
+ * statement.cs: Update to element changes.
+
+ * dispatch.cs: Added, dynamic dispatch utilities.
+
+ * block.cs, main-block.cs: Added.
+
+ * logo-parser.jay: Add "newline" token. Insert elements in correct
+ stacking order based on newlines. Make main tree be a MainBlock.
+
+ * logo-tokenizer.cs: Check for newline.
+
+ * makefile: Reorganize.
+
+ * main.cs: Most code moved into block.cs.
View
12 MonoLOGO/Makefile
@@ -0,0 +1,12 @@
+SUBDIRS=Mono.Languages.Logo mlogo
+
+all:
+ for i in $(SUBDIRS); do \
+ $(MAKE) -C $$i || exit 0; \
+ done
+
+clean:
+ for i in $(SUBDIRS); do \
+ $(MAKE) -C $$i clean || exit 0; \
+ done
+
View
54 MonoLOGO/Mono.Languages.Logo/Makefile
@@ -0,0 +1,54 @@
+all: Mono.Languages.Logo.dll test-target
+
+clean:
+ rm -f Mono.Languages.Logo.dll
+ $(MAKE) -C test clean
+
+MCS=mcs
+
+RUNTIME_SOURCES = \
+ Mono.Languages.Logo.Runtime/CTSMessageTarget.cs \
+ Mono.Languages.Logo.Runtime/DefaultArgumentCountAttribute.cs \
+ Mono.Languages.Logo.Runtime/LogoBinder.cs \
+ Mono.Languages.Logo.Runtime/LogoContext.cs \
+ Mono.Languages.Logo.Runtime/LogoMessageTarget.cs \
+ Mono.Languages.Logo.Runtime/Funcs.cs \
+ Mono.Languages.Logo.Runtime/IMessageStore.cs \
+ Mono.Languages.Logo.Runtime/IMessageStoreCollection.cs \
+ Mono.Languages.Logo.Runtime/IMessageTarget.cs \
+ Mono.Languages.Logo.Runtime/ITypedMessageStore.cs \
+ Mono.Languages.Logo.Runtime/MessageInfo.cs \
+ Mono.Languages.Logo.Runtime/MessageNotSupportedException.cs \
+ Mono.Languages.Logo.Runtime/PassContextAttribute.cs \
+ Mono.Languages.Logo.Runtime/TypedMessageInfo.cs \
+ Mono.Languages.Logo.Runtime/TypedMessageArgument.cs \
+ #
+
+COMPILER_SOURCES = \
+ Mono.Languages.Logo.Compiler/ArgumentInfo.cs \
+ Mono.Languages.Logo.Compiler/Compiler.cs \
+ Mono.Languages.Logo.Compiler/CSharpCompiler.cs \
+ Mono.Languages.Logo.Compiler/Element.cs \
+ Mono.Languages.Logo.Compiler/ElementType.cs \
+ Mono.Languages.Logo.Compiler/Function.cs \
+ Mono.Languages.Logo.Compiler/IndentingWriter.cs \
+ Mono.Languages.Logo.Compiler/InstructionList.cs \
+ Mono.Languages.Logo.Compiler/Interpreter.cs \
+ Mono.Languages.Logo.Compiler/Parser.cs \
+ Mono.Languages.Logo.Compiler/Token.cs \
+ Mono.Languages.Logo.Compiler/TokenList.cs \
+ Mono.Languages.Logo.Compiler/TokenType.cs \
+ Mono.Languages.Logo.Compiler/Tokenizer.cs \
+ #
+
+SOURCES = \
+ $(RUNTIME_SOURCES) \
+ $(COMPILER_SOURCES) \
+ #
+
+Mono.Languages.Logo.dll: $(SOURCES)
+ $(MCS) /target:library /out:Mono.Languages.Logo.dll $(SOURCES)
+
+test-target:
+ $(MAKE) -C test
+
View
14 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/ArgumentInfo.cs
@@ -0,0 +1,14 @@
+namespace Mono.Languages.Logo.Compiler {
+ public struct ArgumentInfo {
+ public string name;
+ public object val;
+ public bool collect;
+
+ public ArgumentInfo (string name, object val, bool collect) {
+ this.name = name;
+ this.val = val;
+ this.collect = collect;
+ }
+ }
+}
+
View
128 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/CSharpCompiler.cs
@@ -0,0 +1,128 @@
+namespace Mono.Languages.Logo.Compiler {
+ using System;
+ using System.Collections;
+ using System.IO;
+
+ using Mono.Languages.Logo.Runtime;
+
+ public class CSharpCompiler : Compiler {
+ private IndentingWriter writer = new IndentingWriter (Console.Out);
+ private int statement_level = 0;
+
+ internal CSharpCompiler (IMessageStoreCollection stores) : base (stores) {
+ }
+
+ protected override void CompileStatement (Element elem) {
+ statement_level++;
+
+ Type[] arg_types = CollectTypes (elem);
+ if (stores.SupportsMessage ((string) elem.Val, arg_types)) {
+ CompileTypedStatement (elem, arg_types);
+ } else {
+ CompileGenericStatement (elem);
+ }
+ statement_level--;
+
+ if (statement_level == 0) {
+ writer.WriteLine (";");
+ }
+ }
+
+ private Type[] CollectTypes (Element elem) {
+ return null;
+ }
+
+ private void CompileGenericStatement (Element elem) {
+ writer.Write ("_funcs.SendMessage (_context, \"{0}\", ", elem.Val);
+ CompileList (elem);
+ writer.Write (")");
+ }
+
+ private void CompileTypedStatement (Element elem, Type[] arg_types) {
+ writer.Write ("Funcs.{0} (", elem.Val);
+ CompileBareList (elem);
+ writer.Write (")");
+ }
+
+
+ private void CompileInfixArg (Element elem) {
+ writer.Write ("((double) ");
+ Compile (elem);
+ writer.Write (")");
+ }
+
+ protected override void CompileInfix (Element elem) {
+ char op = (char) elem.Val;
+
+ if (op == '^') {
+ writer.Write ("System.Math.Pow (");
+ CompileInfixArg (elem.Children[0]);
+ writer.Write (", ");
+ CompileInfixArg (elem.Children[1]);
+ writer.Write (")");
+ return;
+ }
+
+ CompileInfixArg (elem.Children[0]);
+ if (op == '=')
+ writer.Write ("==");
+ else
+ writer.Write (op);
+ CompileInfixArg (elem.Children[1]);
+ }
+
+ protected override void CompileList (Element elem)
+ {
+ writer.Write ("new object[] {");
+ CompileBareList (elem);
+ writer.Write ("}");
+ }
+
+ private void CompileBareList (Element elem)
+ {
+ int i = elem.Children.Count - 1;
+ foreach (Element subelem in elem.Children) {
+ Compile (subelem);
+ if (i > 0)
+ writer.Write (", ");
+ i--;
+ }
+ }
+
+ protected override void CompileLiteral (Element elem)
+ {
+ object val = elem.Val;
+
+ if (val is string)
+ writer.Write ("\"{0}\"", val);
+ else if (val is char)
+ writer.Write ("'{0}'", val);
+ else
+ writer.Write (val);
+ }
+
+ protected override void CompileVariable (Element elem)
+ {
+ writer.Write ("Funcs.Thing (_context, \"{0}\")", (string) elem.Val);
+ }
+
+ protected override void CompileBeginUnit () {
+ writer.WriteLine ("using Mono.Languages.Logo.Runtime;");
+ writer.WriteLine ("class X {");
+ writer.Indent ();
+ writer.WriteLine ("public static void Main () {");
+ writer.Indent ();
+ writer.WriteLine ("LogoContext _context = new LogoContext (null);");
+ writer.WriteLine ("IMessageStoreCollection _funcs = new IMessageStoreCollection ();");
+ writer.WriteLine ("_funcs.Add (new CTSMessageTarget (typeof (Funcs), false));");
+ }
+
+ protected override void CompileFinishUnit () {
+ writer.Deindent ();
+ writer.WriteLine ("}");
+ writer.Deindent ();
+ writer.WriteLine ("}");
+ }
+ }
+}
+
View
62 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Compiler.cs
@@ -0,0 +1,62 @@
+namespace Mono.Languages.Logo.Compiler {
+ using System;
+ using System.Collections;
+ using System.IO;
+
+ using Mono.Languages.Logo.Runtime;
+
+ public abstract class Compiler {
+ protected IMessageStoreCollection stores;
+ private LogoContext context;
+
+ protected Compiler (IMessageStoreCollection stores) {
+ this.stores = stores;
+ context = new LogoContext (null);
+ }
+
+ protected Compiler () {
+ }
+
+ public static Compiler Create (IMessageStoreCollection stores) {
+ return new CSharpCompiler (stores);
+ }
+
+ protected abstract void CompileBeginUnit ();
+ protected abstract void CompileFinishUnit ();
+ protected abstract void CompileStatement (Element elem);
+ protected abstract void CompileInfix (Element elem);
+ protected abstract void CompileList (Element elem);
+ protected abstract void CompileLiteral (Element elem);
+ protected abstract void CompileVariable (Element elem);
+
+ public void Compile (InstructionList list) {
+ CompileBeginUnit ();
+ foreach (Element elem in list) {
+ Compile (elem);
+ }
+ CompileFinishUnit ();
+ }
+
+ public void Compile (Element elem) {
+ switch (elem.Type) {
+ case ElementType.Literal:
+ CompileLiteral (elem);
+ break;
+ case ElementType.List:
+ CompileList (elem);
+ break;
+ case ElementType.Statement:
+ CompileStatement (elem);
+ break;
+ case ElementType.Infix:
+ CompileInfix (elem);
+ break;
+ case ElementType.Variable:
+ CompileVariable (elem);
+ break;
+ default:
+ throw new Exception ();
+ }
+ }
+ }
+}
View
37 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Element.cs
@@ -0,0 +1,37 @@
+namespace Mono.Languages.Logo.Compiler {
+
+ public class Element {
+
+ private ElementType type;
+ private InstructionList children;
+ private object val;
+
+ public ElementType Type {
+ get { return type; }
+ set { type = value; }
+ }
+
+ public InstructionList Children {
+ get { return children; }
+ set { children = value; }
+ }
+
+ public object Val {
+ get { return val; }
+ set { val = value; }
+ }
+
+ public Element (ElementType type, object val) {
+ this.type = type;
+ this.val = val;
+ this.children = null;
+ }
+
+ public Element (ElementType type, object val, InstructionList children) {
+ this.type = type;
+ this.val = val;
+ this.children = children;
+ }
+ }
+}
+
View
13 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/ElementType.cs
@@ -0,0 +1,13 @@
+namespace Mono.Languages.Logo.Compiler {
+ public enum ElementType {
+ Literal,
+ Infix,
+ List,
+ Statement,
+ Class,
+ Variable,
+ Function,
+ QuestionMark
+ };
+}
+
View
100 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Function.cs
@@ -0,0 +1,100 @@
+namespace Mono.Languages.Logo.Compiler {
+ using System;
+ using System.Collections;
+ using Mono.Languages.Logo.Runtime;
+
+ public class Function {
+ string name;
+ TokenList tokens;
+ InstructionList tree;
+ ArgumentInfo[] args;
+ MessageInfo desc;
+
+ public string Name {
+ get { return name; }
+ }
+
+ public MessageInfo Describe () {
+ if (desc != null)
+ return desc;
+
+ desc = new MessageInfo ();
+ desc.message = name;
+ desc.min_argc = 0;
+ desc.max_argc = args.Length;
+
+ foreach (ArgumentInfo info in args) {
+ if (info.val == null && !info.collect)
+ desc.min_argc++;
+ if (info.collect)
+ desc.max_argc = -1;
+ }
+
+ desc.default_argc = desc.min_argc;
+ return desc;
+ }
+
+ public Function (string name, InstructionList tree, ArgumentInfo[] args) {
+ this.name = name;
+ this.tree = tree;
+ this.args = args;
+ }
+
+ public Function (string name, TokenList tokens, ArgumentInfo[] args) {
+ this.name = name;
+ this.tokens = tokens;
+ this.args = args;
+ }
+
+ public void Parse (Parser parser)
+ {
+ if (tree == null)
+ tree = parser.Parse (tokens);
+ }
+
+ private void Debug (ICollection arguments) {
+ Console.Write ("Function.cs (Invoke): {0}", name);
+
+ foreach (object arg in arguments) {
+ Console.Write (" {0}", arg);
+ }
+
+ Console.WriteLine ();
+ }
+
+ public void Invoke (LogoContext context, ICollection arguments, ref object result) {
+ // Debug (arguments);
+
+ LogoContext cc = new LogoContext (context);
+ Hashtable dict = cc.Dict;
+
+ object[] arguments_list = new object[arguments.Count];
+ arguments.CopyTo (arguments_list, 0);
+
+ int i = 0;
+ foreach (ArgumentInfo info in args) {
+ if (i < arguments_list.Length)
+ dict[info.name] = arguments_list[i];
+ else if (info.val != null)
+ dict[info.name] = info.val;
+ i++;
+ }
+
+ // Collect remaining arguments
+ if (args.Length > 0 && args[args.Length - 1].collect) {
+ int col_len = arguments_list.Length - args.Length;
+ if (col_len < 0)
+ col_len = 0;
+ object[] collector = new object[col_len];
+ if (col_len > 0)
+ Array.Copy (arguments_list, args.Length, collector, 0, col_len);
+
+ dict[args[args.Length - 1].name] = collector;
+ }
+
+ Interpreter interp = new Interpreter ((Interpreter) context.CallingEngine, cc);
+ result = interp.Execute (tree);
+ }
+ }
+}
+
View
56 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/IndentingWriter.cs
@@ -0,0 +1,56 @@
+namespace Mono.Languages.Logo.Compiler
+{
+ using System.IO;
+ using System.Text;
+
+ public class IndentingWriter : TextWriter
+ {
+ TextWriter writer;
+ int level;
+ string tab;
+ bool do_indent = true;
+
+ public IndentingWriter (TextWriter writer)
+ {
+ this.writer = writer;
+ this.Level = 0;
+ this.Tab = "\t";
+ }
+
+ public int Level {
+ get { return level; }
+ set { level = value; }
+ }
+
+ public string Tab {
+ get { return tab; }
+ set { tab = value; }
+ }
+
+ public void Indent () {
+ Level = Level + 1;
+ }
+
+ public void Deindent () {
+ Level = Level - 1;
+ }
+
+ public override Encoding Encoding { get { return writer.Encoding; } }
+
+ public override void Write (string value)
+ {
+ if (do_indent) {
+ for (int i = 0; i < level; i++)
+ writer.Write (Tab);
+ do_indent = false;
+ }
+
+ writer.Write (value);
+ }
+
+ public override void WriteLine () {
+ writer.WriteLine ();
+ do_indent = true;
+ }
+ }
+}
View
33 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/InstructionList.cs
@@ -0,0 +1,33 @@
+namespace Mono.Languages.Logo.Compiler {
+
+ using System.Collections;
+
+ public class InstructionList : CollectionBase {
+ public InstructionList (ICollection c) {
+ foreach (Element elem in c) {
+ Add (elem);
+ }
+ }
+
+ public InstructionList () {
+ }
+
+ public int Add (Element elem) {
+ return List.Add (elem);
+ }
+
+ public void Insert (int index, Element elem) {
+ List.Insert (index, elem);
+ }
+
+ public Element this[int index] {
+ get {
+ return (Element) List[index];
+ }
+ set {
+ List[index] = value;
+ }
+ }
+ }
+}
+
View
152 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Interpreter.cs
@@ -0,0 +1,152 @@
+namespace Mono.Languages.Logo.Compiler {
+ using System;
+ using System.Collections;
+ using System.IO;
+
+ using Mono.Languages.Logo.Runtime;
+
+ public class Interpreter {
+ private IMessageStoreCollection stores;
+ private LogoContext context;
+ private object[] template_args;
+
+ public Interpreter (IMessageStoreCollection stores) {
+ this.stores = stores;
+ context = new LogoContext (null);
+ }
+
+ public Interpreter (Interpreter interp, LogoContext context) {
+ this.stores = interp.stores;
+ this.context = context;
+ }
+
+ private object[] CollectArgs (InstructionList children) {
+ object[] args = new object[children.Count];
+
+ int i = 0;
+ foreach (Element subelem in children) {
+ object val;
+ switch (subelem.Type) {
+ case ElementType.Literal:
+ val = subelem.Val;
+ break;
+ case ElementType.Infix:
+ val = ExecuteInfix (subelem);
+ break;
+ case ElementType.List:
+ val = ConstructList (subelem);
+ break;
+ case ElementType.Statement:
+ val = ExecuteStatement (subelem);
+ break;
+ case ElementType.Variable:
+ val = Funcs.Thing (context, (string) subelem.Val);
+ break;
+ default:
+ throw new Exception ();
+ }
+
+ args[i] = val;
+ i++;
+ }
+
+ return args;
+ }
+
+ private object ExecuteStatement (Element elem) {
+ object ret = null;
+ object[] args = CollectArgs (elem.Children);
+
+ context.CallingEngine = this;
+ ret = stores.SendMessage (context, (string) elem.Val, args);
+ context.CallingEngine = null;
+ return ret;
+ }
+
+ private object ExecuteInfix (Element elem) {
+ object[] args = CollectArgs (elem.Children);
+ double a = (double) args[0];
+ double b = (double) args[1];
+ switch ((char) elem.Val) {
+ case '+':
+ return a + b;
+ case '-':
+ return a - b;
+ case '*':
+ return a * b;
+ case '/':
+ return a / b;
+ case '^':
+ return Math.Pow (a, b);
+ case '=':
+ return a == b;
+ case '<':
+ return a < b;
+ case '>':
+ return a > b;
+ default:
+ throw new Exception ();
+ }
+ }
+
+ private object ConstructList (Element elem) {
+ object[] list = new object[elem.Children.Count];
+ int i = 0;
+ foreach (Element subelem in elem.Children) {
+ if (subelem.Type == ElementType.List)
+ list[i] = ConstructList (subelem);
+ else
+ list[i] = subelem.Val;
+ i++;
+ }
+
+ return list;
+ }
+
+ public object Execute (InstructionList list) {
+ foreach (Element elem in list) {
+ switch (elem.Type) {
+ case ElementType.Literal:
+ return elem.Val;
+ case ElementType.List:
+ return ConstructList (elem);
+ case ElementType.Statement:
+ ExecuteStatement (elem);
+ if (context.StopExecution)
+ return context.OutputValue;
+ break;
+ case ElementType.Infix:
+ ExecuteInfix (elem);
+ break;
+ case ElementType.Variable:
+ return Funcs.Thing (context, (string) elem.Val);
+ default:
+ throw new Exception ();
+ }
+ }
+
+ return null;
+ }
+
+ public static object Execute (LogoContext context, ICollection runlist, params object[] template_args) {
+ string[] runlist_strs = new string[runlist.Count];
+ int i = 0;
+ foreach (object o in runlist) {
+ if (o is ICollection)
+ runlist_strs[i] = Funcs.ListToString ((ICollection) o, 0, true);
+ else
+ runlist_strs[i] = o.ToString ();
+ i++;
+ }
+
+ Interpreter interp = new Interpreter ((Interpreter) context.CallingEngine, context);
+ interp.template_args = template_args;
+
+ Parser parser = new Parser (interp.stores, null);
+ parser.AllowQuestionMark = true;
+ InstructionList tree = parser.Parse (runlist_strs);
+
+ return interp.Execute (tree);
+ }
+ }
+}
View
429 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Parser.cs
@@ -0,0 +1,429 @@
+namespace Mono.Languages.Logo.Compiler {
+ using System;
+ using System.Collections;
+ using System.IO;
+
+ using Mono.Languages.Logo.Runtime;
+
+ public class Parser {
+ private Tokenizer tokenizer = new Tokenizer ();
+ private IMessageStoreCollection stores;
+ private LogoMessageTarget funcs;
+ private ArrayList to_parse;
+
+ public Parser () {
+ stores = new IMessageStoreCollection ();
+ }
+
+ public Parser (IMessageStoreCollection stores, LogoMessageTarget funcs) {
+ this.stores = stores;
+ this.funcs = funcs;
+ }
+
+ public bool AllowQuestionMark {
+ get { return tokenizer.AllowQuestionMark; }
+ set { tokenizer.AllowQuestionMark = value; }
+ }
+
+ public InstructionList Parse (TextReader reader) {
+ return Parse (tokenizer.Parse (reader));
+ }
+
+ public InstructionList Parse (string content) {
+ return Parse (tokenizer.Parse (content));
+ }
+
+ public InstructionList Parse (string[] content) {
+ return Parse (tokenizer.Parse (content));
+ }
+
+ public InstructionList Parse (TokenList tokens) {
+ TokenList partial = ParseForwards (tokens);
+ partial = ParseInfix (partial);
+ InstructionList tree = ParseBackwards (partial, false);
+
+ if (to_parse != null) {
+ // Null out the member before going re-entrant.
+ // Otherwise we could go into an infinite loop.
+ ArrayList parse_now = to_parse;
+ to_parse = null;
+
+ foreach (Function f in parse_now) {
+ f.Parse (this);
+ }
+ }
+
+ return tree;
+ }
+
+ private Element ParseList (IEnumerator iterator) {
+ InstructionList list = new InstructionList ();
+ while (iterator.MoveNext ()) {
+ Token token = (Token) iterator.Current;
+ if (token.Type == TokenType.CloseBracket)
+ break;
+ else if (token.Type == TokenType.OpenBracket)
+ list.Add (ParseList (iterator));
+ else
+ list.Add (new Element (ElementType.Literal, token.Val));
+ }
+
+ return new Element (ElementType.List, null, list);
+ }
+
+ private int CountArgs (string word, bool use_maximum) {
+ MessageInfo info = stores.DescribeMessage (word);
+ if (use_maximum)
+ return info.max_argc;
+ else
+ return info.default_argc;
+ }
+
+ private TokenList ParseForwards (TokenList tokens) {
+ TokenList partial = new TokenList ();
+ ParseForwards (partial, tokens.GetEnumerator (), 0);
+ return partial;
+ }
+
+ private TokenList ParseBrackets (IEnumerator iterator) {
+ TokenList list = new TokenList ();
+
+ while (iterator.MoveNext ()) {
+ Token token = (Token) iterator.Current;
+ if (token.Type == TokenType.CloseBracket)
+ break;
+ else
+ list.Add (token);
+ }
+
+ return list;
+ }
+
+ private void PrintFunction (TokenList func) {
+ Console.Write ("function {0}", (string) func[0].Val);
+ foreach (Token token in (TokenList) func[1].Val) {
+ if (token.Type == TokenType.Variable)
+ Console.Write (" :{0}", token.Val);
+ else if (token.Type == TokenType.PlaceholderElement) {
+ TokenList arg = (TokenList) ((Element) token.Val).Val;
+ Console.Write (" [");
+ int j = 0;
+ foreach (Token t in arg) {
+ if (j == 0)
+ Console.Write (":");
+ Console.Write (t.Val);
+ if (j < (arg.Count - 1))
+ Console.Write (" ");
+ j++;
+ }
+ Console.Write ("]");
+ }
+ }
+ Console.WriteLine ();
+
+ bool print_space = false;
+ bool print_tab = true;
+ foreach (Token token in (TokenList) func[2].Val) {
+ if (print_space && token.Type != TokenType.Newline)
+ Console.Write (" ");
+ else
+ print_space = true;
+
+ if (print_tab) {
+ Console.Write ("\t");
+ print_tab = false;
+ }
+
+ if (token.Type == TokenType.Newline) {
+ print_tab = true;
+ print_space = false;
+ }
+
+ Console.Write ("{0}", token.Val);
+ }
+
+ Console.WriteLine ();
+ }
+
+ private Function CreateFunction (TokenList func) {
+ string name = (string) func[0].Val;
+
+ ArrayList args_list = new ArrayList ();
+ foreach (Token token in (TokenList) func[1].Val) {
+ ArgumentInfo info = new ArgumentInfo ();
+
+ if (token.Type == TokenType.Variable)
+ info = new ArgumentInfo ((string) token.Val, null, false);
+ else if (token.Type == TokenType.PlaceholderElement) {
+ TokenList arg = (TokenList) ((Element) token.Val).Val;
+ // FIXME: What if it is longer than 2 elements?
+ if (arg.Count > 1)
+ info = new ArgumentInfo ((string) arg[0].Val, arg[1].Val, false);
+ else
+ info = new ArgumentInfo ((string) arg[0].Val, null, true);
+ }
+
+ args_list.Add (info);
+ }
+ ArgumentInfo[] args = (ArgumentInfo[]) args_list.ToArray (typeof (ArgumentInfo));
+ TokenList tokens = (TokenList) func[2].Val;
+
+ return new Function (name, tokens, args);
+ }
+
+ private enum ParseToState {
+ FunctionName,
+ Argument,
+ ArgumentWithValue,
+ ArgumentCollector,
+ Content
+ }
+
+ private ParseToState AdvanceState (ParseToState state) {
+ return (ParseToState) ((int) state + 1);
+ }
+
+ private Token ParseTo (IEnumerator iterator) {
+ ParseToState state = ParseToState.FunctionName;
+ Token name = new Token (TokenType.Word, null);
+ TokenList args = new TokenList ();
+ TokenList def = new TokenList ();
+
+ bool reading = true;
+ bool prev_newline = false;
+ while (reading && iterator.MoveNext ()) {
+ Token token = (Token) iterator.Current;
+
+ if (state != ParseToState.Content && token.Type == TokenType.Newline) {
+ state = ParseToState.Content;
+ prev_newline = true;
+ continue;
+ }
+
+ switch (state) {
+ case ParseToState.FunctionName:
+ name = token;
+ state = AdvanceState (state);
+ break;
+ case ParseToState.Argument:
+ case ParseToState.ArgumentWithValue:
+ case ParseToState.ArgumentCollector:
+ if (token.Type == TokenType.OpenBracket) {
+ TokenList arg = ParseBrackets (iterator);
+ if (state == ParseToState.Argument || (state == ParseToState.ArgumentWithValue && arg.Count == 1)) {
+ state = AdvanceState (state);
+ }
+ args.Add (new Token (TokenType.PlaceholderElement, new Element (ElementType.List, arg)));
+ } else {
+ args.Add (token);
+ }
+ break;
+ case ParseToState.Content:
+ if (prev_newline && token.Type == TokenType.Word && String.Compare ((string) token.Val, "end", true) == 0) {
+ reading = false;
+ } else {
+ def.Add (token);
+ prev_newline = (token.Type == TokenType.Newline);
+ }
+ break;
+ }
+ }
+
+ TokenList func = new TokenList ();
+ func.Add (name);
+ func.Add (new Token (TokenType.PlaceholderGroup, args));
+ func.Add (new Token (TokenType.PlaceholderGroup, def));
+
+ Function func_obj = CreateFunction (func);
+ funcs.AddMessage (func_obj);
+
+ if (to_parse == null)
+ to_parse = new ArrayList ();
+ to_parse.Add (func_obj);
+
+ return new Token (TokenType.PlaceholderElement, new Element (ElementType.Function, func_obj));
+ }
+
+ private void ParseForwards (TokenList partial, IEnumerator iterator, int parens) {
+ while (iterator.MoveNext ()) {
+ Token token = (Token) iterator.Current;
+ switch (token.Type) {
+ case TokenType.OpenBracket:
+ partial.Add (new Token (TokenType.PlaceholderElement, ParseList (iterator)));
+ break;
+ case TokenType.OpenParens:
+ TokenList inner = new TokenList ();
+ ParseForwards (inner, iterator, parens + 1);
+ partial.Add (new Token (TokenType.PlaceholderGroup, inner));
+ break;
+ case TokenType.CloseParens:
+ return;
+ case TokenType.Word:
+ if (String.Compare ((string) token.Val, "to", true) == 0) {
+ // FIXME: Usual case is in void context
+ // token = ParseTo (iterator);
+ ParseTo (iterator);
+ } else {
+ partial.Add (token);
+ }
+ break;
+ default:
+ partial.Add (token);
+ break;
+ }
+ }
+ }
+
+ private void ExtendList (TokenList list, Stack stack) {
+ Array tokens = stack.ToArray ();
+ Array.Reverse (tokens);
+ list.Extend (tokens);
+ }
+
+ private int Weight (Token token) {
+ char c = (char) token.Val;
+ if (c == '^') {
+ return 4;
+ } else if (c == '*' || c == '/' || c == '\\') {
+ return 3;
+ } else if (c == '+' || c == '-') {
+ return 2;
+ } else if (c == '=' || c == '<' || c == '>') {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ private TokenList ParseInfix (TokenList partial) {
+ TokenList output = new TokenList ();
+ Stack stack = new Stack ();
+ bool last_was_operand = false;
+
+ int length = partial.Count;
+ for (int i = length - 1; i >= 0; i--) {
+ Token token = partial[i];
+ if (token.Type == TokenType.Word) {
+ ExtendList (output, stack);
+ output.Add (token);
+ stack.Clear ();
+ } else if (token.Type == TokenType.Infix) {
+ if (stack.Count == 0) {
+ stack.Push (token);
+ } else {
+ Token prev = (Token) stack.Pop ();
+ if (Weight (prev) <= Weight (token)) {
+ stack.Push (token);
+ stack.Push (prev);
+ } else {
+ output.Add (prev);
+ stack.Push (token);
+ }
+ }
+ last_was_operand = false;
+ } else {
+ if (token.Type == TokenType.PlaceholderGroup) {
+ token.Val = ParseInfix ((TokenList) token.Val);
+ }
+
+ if (i > 0) {
+ Token peek = partial[i - 1];
+ if (peek.Type == TokenType.Minus) {
+ output.Add (token);
+ output.Add (peek);
+ last_was_operand = true;
+ i--;
+ continue;
+ }
+ }
+
+ if (last_was_operand) {
+ ExtendList (output, stack);
+ stack.Clear ();
+ }
+ output.Add (token);
+ last_was_operand = true;
+ }
+ }
+
+ ExtendList (output, stack);
+ output.Reverse ();
+ return output;
+ }
+
+ private InstructionList ParseBackwards (TokenList tokens, bool grouped) {
+ Stack stack = new Stack ();
+
+ for (int i = tokens.Count - 1; i >= 0; i--) {
+ Token token = tokens[i];
+
+ switch (token.Type) {
+ case TokenType.Number:
+ case TokenType.String:
+ stack.Push (new Element (ElementType.Literal, token.Val));
+ break;
+ case TokenType.PlaceholderElement:
+ stack.Push (token.Val);
+ break;
+ case TokenType.PlaceholderGroup:
+ InstructionList group = ParseBackwards ((TokenList) token.Val, true);
+ if (group.Count == 1) {
+ stack.Push (group[0]);
+ } else if (group.Count == 0) {
+ } else {
+ throw new Exception ("Unexpected grouping");
+ }
+ break;
+ case TokenType.Word:
+ case TokenType.Infix:
+ case TokenType.Minus:
+ InstructionList inner = new InstructionList ();
+
+ int count;
+ ElementType etype;
+ if (token.Type == TokenType.Word) {
+ count = CountArgs ((string) token.Val, grouped && i == 0);
+ if (count == -1)
+ count = stack.Count;
+ etype = ElementType.Statement;
+ } else if (token.Type == TokenType.Minus) {
+ count = 1;
+ etype = ElementType.Statement;
+ token.Val = "Minus";
+ } else {
+ count = 2;
+ etype = ElementType.Infix;
+ }
+
+ for (int j = 0; j < count; j++)
+ inner.Add ((Element) stack.Pop ());
+
+ stack.Push (new Element (etype, token.Val, inner));
+ break;
+ case TokenType.Newline:
+ break;
+ case TokenType.Variable:
+ stack.Push (new Element (ElementType.Variable, token.Val));
+ break;
+ case TokenType.QuestionMark:
+ // Don't need to check AllowQuestionMark here as the
+ // tokenizer checks already,
+ stack.Push (new Element (ElementType.QuestionMark, token.Val));
+ break;
+ case TokenType.PlaceholderFunction:
+ default:
+ throw new Exception ("Unexpected token: " + token.Type + "<" + token.Val + ">");
+ }
+ }
+
+ InstructionList tree = new InstructionList ();
+ object[] toplevel = stack.ToArray ();
+ foreach (object o in toplevel) {
+ tree.Add ((Element) o);
+ }
+
+ return tree;
+ }
+ }
+}
+
View
11 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Token.cs
@@ -0,0 +1,11 @@
+namespace Mono.Languages.Logo.Compiler {
+ public struct Token {
+ public TokenType Type;
+ public object Val;
+
+ public Token (TokenType type, object val) {
+ Type = type;
+ Val = val;
+ }
+ }
+}
View
45 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/TokenList.cs
@@ -0,0 +1,45 @@
+namespace Mono.Languages.Logo.Compiler {
+
+ using System.Collections;
+
+ public class TokenList : CollectionBase {
+ public TokenList (ICollection c) {
+ foreach (Token token in c) {
+ Add (token);
+ }
+ }
+
+ public TokenList () {
+ }
+
+ public int Add (Token token) {
+ return List.Add (token);
+ }
+
+ public Token this[int index] {
+ get {
+ return (Token) List[index];
+ }
+ set {
+ List[index] = value;
+ }
+ }
+
+ public void Extend (ICollection tokens) {
+ foreach (Token token in tokens) {
+ List.Add (token);
+ }
+ }
+
+ public void Reverse () {
+ IList list = List;
+ int length = list.Count;
+ for (int i = 0; i < length / 2; i++) {
+ object tmp = list[i];
+ list[i] = list[length - i - 1];
+ list[length - i - 1] = tmp;
+ }
+ }
+ }
+}
+
View
19 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/TokenType.cs
@@ -0,0 +1,19 @@
+namespace Mono.Languages.Logo.Compiler {
+ public enum TokenType {
+ Word,
+ Number,
+ String,
+ Minus,
+ Infix,
+ OpenParens,
+ CloseParens,
+ OpenBracket,
+ CloseBracket,
+ Variable,
+ Newline,
+ QuestionMark,
+ PlaceholderGroup,
+ PlaceholderElement,
+ PlaceholderFunction
+ }
+}
View
251 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Compiler/Tokenizer.cs
@@ -0,0 +1,251 @@
+namespace Mono.Languages.Logo.Compiler {
+ using System;
+ using System.Collections;
+ using System.IO;
+ using System.Text;
+
+ public class Tokenizer {
+ private bool allow_question_mark = false;
+
+ private static bool IsWhitespace (char c) {
+ return (c == ' ' || c == '\t');
+ }
+
+ private static bool IsNewline (char c) {
+ return (c == '\n');
+ }
+
+ private static bool IsInfix (char c) {
+ return (c == '+' ||
+ c == '-' ||
+ c == '*' ||
+ c == '/' ||
+ c == '\\' ||
+ c == '^' ||
+ c == '=' ||
+ c == '<' ||
+ c == '>');
+ }
+
+ private static bool IsDelimiter (char c) {
+ return (IsWhitespace (c) || IsNewline (c) ||
+ IsInfix (c) ||
+ c == '(' ||
+ c == ')' ||
+ c == '[' ||
+ c == ']' ||
+ c == ';');
+ }
+
+ private static bool IsSpecial (char c) {
+ return (c == '{' ||
+ c == '}' ||
+ c == '|' ||
+ c == '_');
+ }
+
+ private static bool IsNumber (string str, out double num) {
+ num = 0;
+
+ if (str.Length == 1 && IsInfix (str[0]))
+ return false;
+
+ try {
+ num = Double.Parse (str);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private static bool IsNumber (char c) {
+ double num;
+ return IsNumber (new String (c, 1), out num);
+ }
+
+ private static bool IsVariable (string str, out string name) {
+ if (str.Length > 1 && str[0] == ':') {
+ name = str.Substring (1);
+ return true;
+ } else {
+ name = String.Empty;
+ return false;
+ }
+ }
+
+ private static bool IsString (string str, out string val) {
+ if (str.Length > 1 && str[0] == '"') {
+ val = str.Substring (1);
+ return true;
+ } else {
+ val = String.Empty;
+ return false;
+ }
+ }
+
+ private static bool IsSymbolStart (char c) {
+ return (c == '"' ||
+ c == '|' ||
+ c == ':' ||
+ !(IsDelimiter (c) || IsSpecial (c) || IsNumber (c)));
+ }
+
+ public bool AllowQuestionMark {
+ get { return allow_question_mark; }
+ set { allow_question_mark = value; }
+ }
+
+ private Token TokenForChar (int c_prev_int, int c_peek_int, char c) {
+ if (c == '-') {
+ TokenType type;
+ if (c_prev_int == -1)
+ type = TokenType.Minus;
+ else if (c_peek_int == -1)
+ type = TokenType.Infix;
+ else {
+ char c_prev = (char) c_prev_int;
+ char c_peek = (char) c_peek_int;
+ if (IsNumber (c_peek) || IsSymbolStart (c_peek) || c_peek == '(') {
+ if (c_prev == ')')
+ type = TokenType.Infix;
+ else
+ type = TokenType.Minus;
+ } else {
+ type = TokenType.Infix;
+ }
+ }
+ return new Token (type, c);
+ } else if (c == '(')
+ return new Token (TokenType.OpenParens, c);
+ else if (c == ')')
+ return new Token (TokenType.CloseParens, c);
+ else if (c == '[')
+ return new Token (TokenType.OpenBracket, c);
+ else if (c == ']')
+ return new Token (TokenType.CloseBracket, c);
+ else if (c == '\n')
+ return new Token (TokenType.Newline, c);
+ else if (IsInfix (c))
+ return new Token (TokenType.Infix, c);
+ else if (allow_question_mark && c == '?')
+ return new Token (TokenType.QuestionMark, c);
+ else
+ throw new Exception ("Unexpected input: " + c);
+ }
+
+ private StringBuilder AddTokens (TokenList tokens, StringBuilder builder, int c_prev_int, int c_peek_int) {
+ StringBuilder ret;
+ string val = builder.ToString ();
+
+ if (val.Length > 0) {
+ ret = new StringBuilder ();
+ } else {
+ ret = builder;
+ }
+
+ double as_num;
+ if (IsNumber (val, out as_num)) {
+ Token token = new Token (TokenType.Number, as_num);
+ if (tokens[tokens.Count - 1].Type == TokenType.Minus) {
+ token.Val = -((double) token.Val);
+ tokens[tokens.Count - 1] = token;
+ } else {
+ tokens.Add (token);
+ }
+ } else if (val.Length > 1) {
+ Token token;
+
+ string var_name, str_val;
+ if (IsVariable (val, out var_name))
+ token = new Token (TokenType.Variable, var_name);
+ else if (IsString (val, out str_val))
+ token = new Token (TokenType.String, str_val);
+ else
+ token = new Token (TokenType.Word, val);
+
+ tokens.Add (token);
+ } else if (val.Length == 1) {
+ tokens.Add (TokenForChar (c_prev_int, c_peek_int, val[0]));
+ }
+
+ return ret;
+ }
+
+ private StringBuilder AddTokens (TokenList tokens, StringBuilder builder, int c_prev_int, int c_peek_int, char c) {
+ StringBuilder ret = AddTokens (tokens, builder, c_prev_int, c_peek_int);
+
+ if (!(IsWhitespace (c) || IsSpecial (c)))
+ tokens.Add (TokenForChar (c_prev_int, c_peek_int, c));
+
+ return ret;
+ }
+
+ public TokenList Parse (string content) {
+ return Parse (new StringReader (content));
+ }
+
+ public TokenList Parse (string[] content) {
+ return Parse (String.Join (" ", content));
+ }
+
+ public TokenList Parse (TextReader reader) {
+ TokenList tokens = new TokenList ();
+
+ StringBuilder builder = new StringBuilder ();
+ int c_int, c_prev_int = -1;
+ bool inside_bars = false;
+ bool ignore_bar = false;
+ bool inside_comment = false;
+ for (c_int = reader.Read (); c_int != -1; c_prev_int = c_int, c_int = reader.Read ()) {
+ char c = (char) c_int;
+
+ if (inside_comment) {
+ if (IsNewline (c)) {
+ inside_comment = false;
+ } else {
+ continue;
+ }
+ }
+
+ if (c == '|') {
+ if (ignore_bar) {
+ ignore_bar = false;
+ continue;
+ }
+
+ if (inside_bars && reader.Peek () == (int) '|') {
+ ignore_bar = true;
+ builder.Append ('|');
+ continue;
+ }
+
+ inside_bars = !inside_bars;
+ continue;
+ }
+
+ if (inside_bars) {
+ builder.Append (c);
+ continue;
+ }
+
+ if (c == '_' && tokens.Count > 0 && tokens[tokens.Count - 1].Type == TokenType.Newline) {
+ tokens.RemoveAt (tokens.Count - 1);
+ continue;
+ } else if (c == ';') {
+ inside_comment = true;
+ continue;
+ } else if (!IsDelimiter (c) || c_prev_int == (int) '"') {
+ builder.Append (c);
+ continue;
+ }
+
+ builder = AddTokens (tokens, builder, c_prev_int, reader.Peek (), c);
+ }
+
+ builder = AddTokens (tokens, builder, c_prev_int, reader.Peek ());
+
+ return tokens;
+ }
+ }
+}
+
View
204 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/CTSMessageTarget.cs
@@ -0,0 +1,204 @@
+namespace Mono.Languages.Logo.Runtime {
+ using System;
+ using System.Collections;
+ using System.Reflection;
+
+ public class CTSMessageTarget : IMessageTarget, IMessageStore, ITypedMessageStore {
+ private object obj;
+ private Type obj_type;
+ private bool wrap_obj;
+ private static LogoBinder binder = new LogoBinder (null);
+
+ public object TargetObject {
+ get {
+ return obj;
+ }
+ }
+
+ private void Init (object obj) {
+ if (obj is Type) {
+ this.obj = null;
+ this.obj_type = (Type) obj;
+ } else {
+ this.obj = obj;
+ this.obj_type = obj.GetType ();
+ }
+ }
+
+ public CTSMessageTarget (object obj, bool wrap_obj) {
+ Init (obj);
+ this.wrap_obj = wrap_obj;
+ }
+
+ public CTSMessageTarget (object obj) {
+ Init (obj);
+ this.wrap_obj = true;
+ }
+
+ // IMessageTarget
+ public object SendMessage (LogoContext context, string message, ICollection arguments) {
+ object[] args_array = new object[arguments.Count];
+
+ int i = 0;
+ foreach (object o in arguments) {
+ if (o is CTSMessageTarget) {
+ args_array[i] = ((CTSMessageTarget) o).TargetObject;
+ } else {
+ args_array[i] = o;
+ }
+ i++;
+ }
+
+ binder.Context = context;
+ object target_obj = obj;
+ object raw_result = obj_type.InvokeMember (message, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.InvokeMethod, binder, target_obj, args_array);
+
+ if (!wrap_obj ||
+ raw_result == null ||
+ raw_result is IMessageTarget ||
+ raw_result.GetType ().IsPrimitive) {
+ return raw_result;
+ } else {
+ return new CTSMessageTarget (raw_result);
+ }
+ }
+
+ private MessageInfo[] ListMessages (string opt_filter) {
+ ICollection method_list;
+ if (obj == null) {
+ ArrayList list = new ArrayList (obj_type.GetMethods ());
+ list.InsertRange (list.Count, typeof (Type).GetMethods ());
+ method_list = list;
+ } else {
+ method_list = obj_type.GetMethods ();
+ }
+
+ ArrayList info_list = new ArrayList ();
+ Hashtable methods = new Hashtable ();
+
+ if (opt_filter != String.Empty) {
+ opt_filter = opt_filter.ToLower ();
+ }
+
+ foreach (MethodInfo method in method_list)
+ {
+ string method_lower = method.Name.ToLower ();
+ if (opt_filter != String.Empty && method.Name.ToLower () != opt_filter)
+ continue;
+
+ MessageInfo info = (MessageInfo) methods[method_lower];
+ if (info == null) {
+ info = new TypedMessageInfo ();
+ info.message = method.Name;
+ info.min_argc = -1;
+ info.default_argc = -1;
+ info.max_argc = 0;
+ methods[method_lower] = info;
+ info_list.Add (info);
+ }
+
+ ParameterInfo[] parms = method.GetParameters ();
+ int count = (parms != null) ? parms.Length : 0;
+
+ if (count > 0) {
+ object[] attrs = parms[count - 1].GetCustomAttributes (typeof (System.ParamArrayAttribute), true);
+ if (attrs != null && attrs.Length > 0)
+ info.max_argc = -1;
+ }
+
+ object[] method_attrs = method.GetCustomAttributes (typeof (PassContextAttribute), true);
+ if (method_attrs != null && method_attrs.Length > 0) {
+ count--;
+ }
+
+ if (info.min_argc == -1 || count <= info.min_argc) {
+ info.min_argc = count;
+ info.default_argc = count;
+ }
+
+ method_attrs = method.GetCustomAttributes (typeof (DefaultArgumentCountAttribute), true);
+ if (method_attrs != null && method_attrs.Length > 0) {
+ info.default_argc = ((DefaultArgumentCountAttribute) method_attrs[0]).DefaultCount;
+ }
+
+ if (info.max_argc != -1 && count > info.max_argc) {
+ info.max_argc = count;
+ }
+ }
+
+ MessageInfo[] ret = new MessageInfo[info_list.Count];
+ info_list.CopyTo (ret, 0);
+ return ret;
+ }
+
+ // IMessageStore
+
+ public MessageInfo DescribeMessage (string message) {
+ MessageInfo[] info = ListMessages (message);
+ if (info.Length > 0)
+ return info[0];
+ else
+ return null;
+ }
+
+ public bool SupportsMessage (string message) {
+ MethodInfo[] methods = obj_type.GetMethods ();
+ foreach (MethodInfo method in methods) {
+ if (String.Compare (method.Name, message, true) == 0) {
+ return true;
+ }
+ }
+
+ methods = typeof (Type).GetMethods ();
+ foreach (MethodInfo method in methods) {
+ if (String.Compare (method.Name, message, true) == 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public MessageInfo[] SupportedMessages {
+ get {
+ return ListMessages (String.Empty);
+ }
+ }
+
+ // ITypedMessageStore
+
+ public bool SupportsMessage (string message, Type[] args) {
+ // FIXME: This is the lazy approach. It does not
+ // compare against types, it only sees if there
+ // is only one, unambiguous, message
+
+ bool supports = false;
+ MethodInfo[] methods = obj_type.GetMethods ();
+ foreach (MethodInfo method in methods) {
+ if (String.Compare (method.Name, message, true) == 0) {
+ if (supports)
+ return false;
+ else
+ supports = true;
+ }
+ }
+
+ methods = typeof (Type).GetMethods ();
+ foreach (MethodInfo method in methods) {
+ if (String.Compare (method.Name, message, true) == 0) {
+ if (supports)
+ return false;
+ else
+ supports = true;
+ }
+ }
+
+ return supports;
+ }
+
+ public TypedMessageInfo DescribeMessage (string message, Type[] args) {
+ return (TypedMessageInfo) DescribeMessage (message);
+ }
+ }
+}
+
View
17 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/DefaultArgumentCountAttribute.cs
@@ -0,0 +1,17 @@
+namespace Mono.Languages.Logo.Runtime {
+ using System;
+
+ [AttributeUsage (AttributeTargets.Method)]
+ public class DefaultArgumentCountAttribute : Attribute {
+ private int def;
+
+ public DefaultArgumentCountAttribute (int def) {
+ this.def = def;
+ }
+
+ public int DefaultCount {
+ get { return def; }
+ }
+ }
+}
+
View
269 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/Funcs.cs
@@ -0,0 +1,269 @@
+namespace Mono.Languages.Logo.Runtime {
+ using System;
+ using System.Collections;
+ using System.Text;
+ using Mono.Languages.Logo.Compiler;
+
+ public class Funcs {
+ // Word primitives
+ public static char First (string str) {
+ if (str.Length < 1)
+ throw new ArgumentException (String.Empty, "str");
+ return str[0];
+ }
+
+ public static string ButFirst (string str) {
+ if (str.Length == 0)
+ throw new ArgumentException (String.Empty, "str");
+ else if (str.Length == 1)
+ return String.Empty;
+ else
+ return str.Substring (1);
+ }
+
+ public static char Last (string str) {
+ if (str.Length < 1)
+ throw new ArgumentException (String.Empty, "str");
+ return str[str.Length - 1];
+ }
+
+ public static string ButLast (string str) {
+ if (str.Length == 0)
+ throw new ArgumentException (String.Empty, "str");
+ else if (str.Length == 1)
+ return String.Empty;
+ else
+ return str.Substring (0, str.Length - 1);
+ }
+
+ public static char Item (int index, string str) {
+ if (index >= str.Length)
+ throw new ArgumentOutOfRangeException ("index");
+ return str[index];
+ }
+
+ public static int Count (string str) {
+ return str.Length;
+ }
+
+ // List primitives
+ public static object First (ICollection list) {
+ if (list.Count < 1)
+ throw new ArgumentException (String.Empty, "list");
+ IEnumerator iterator = list.GetEnumerator ();
+ iterator.MoveNext ();
+ return iterator.Current;
+ }
+
+ public static object First (IList list) {
+ if (list.Count < 1)
+ throw new ArgumentException (String.Empty, "list");
+ return list[0];
+ }
+
+ public static object Firsts (ICollection list) {
+ object[] fs = new object[list.Count];
+
+ int i = 0;
+ foreach (ICollection sublist in list) {
+ fs[i] = First (sublist);
+ i++;
+ }
+
+ return fs;
+ }
+
+ public static object ButFirst (ICollection list) {
+ if (list.Count == 0)
+ throw new ArgumentException (String.Empty, "list");
+ else if (list.Count == 1)
+ return new object[0];
+ else {
+ object[] as_array = new object[list.Count];
+ object[] bf = new object[list.Count - 1];
+ list.CopyTo (as_array, 0);
+ Array.Copy (as_array, 1, bf, 0, list.Count - 1);
+ return bf;
+ }
+ }
+
+ public static object ButFirsts (ICollection list) {
+ object[] bfs = new object[list.Count];
+
+ int i = 0;
+ foreach (ICollection sublist in list) {
+ bfs[i] = ButFirst (sublist);
+ i++;
+ }
+
+ return bfs;
+ }
+
+ public static object Last (ICollection list) {
+ if (list.Count < 1)
+ throw new ArgumentException (String.Empty, "list");
+ int i = 0;
+ int end = list.Count - 1;
+ foreach (object val in list) {
+ if (i == end)
+ return val;
+ i++;
+ }
+
+ return null;
+ }
+
+ public static object Last (IList list) {
+ if (list.Count < 1)
+ throw new ArgumentException (String.Empty, "list");
+ return list[list.Count - 1];
+ }
+
+ public static object ButLast (ICollection list) {
+ if (list.Count == 0)
+ throw new ArgumentException (String.Empty, "list");
+ else if (list.Count == 1)
+ return new object[0];
+ else {
+ object[] as_array = new object[list.Count];
+ object[] bf = new object[list.Count - 1];
+ list.CopyTo (as_array, 0);
+ Array.Copy (as_array, 0, bf, 1, list.Count - 1);
+ return bf;
+ }
+ }
+
+ public static object Item (int index, ICollection list) {
+ if (index >= list.Count)
+ throw new ArgumentOutOfRangeException ("index");
+ else {
+ int i = 0;
+ foreach (object val in list) {
+ if (i == index)
+ return val;
+ i++;
+ }
+ }
+
+ return null;
+ }
+
+ public static object Item (int index, IList list) {
+ if (index >= list.Count)
+ throw new ArgumentOutOfRangeException ("index");
+ else
+ return list[index];
+ }
+
+ public static int Count (ICollection list) {
+ return list.Count;
+ }
+
+ // Streams and I/O
+ private static void ListToString (StringBuilder sb, ICollection list, int outer_brackets, bool spaces) {
+ if (outer_brackets == 0)
+ sb.Append ('[');
+
+ int i = 0;
+ int end = list.Count - 1;
+ foreach (object val in list) {
+ if (val is ICollection)
+ ListToString (sb, (ICollection) val, (outer_brackets == 0) ? 0 : (outer_brackets - 1), true);
+ else
+ sb.Append (val.ToString ());
+ if (spaces && i < end)
+ sb.Append (" ");
+ i++;
+ }
+
+ if (outer_brackets == 0)
+ sb.Append (']');
+ }
+
+ internal static string ListToString (ICollection list, int outer_brackets, bool spaces) {
+ StringBuilder sb = new StringBuilder ();
+ ListToString (sb, list, outer_brackets, spaces);
+ return sb.ToString ();
+ }
+
+ // LAMESPEC: ObjectLOGO seems to differ slightly from UCB Logo
+ // in allowed input lengths. As UCB is more permissive, these
+ // functions follow it for now
+
+ public static void Print (params object[] vals) {
+ Console.WriteLine (ListToString (vals, 2, true));
+ }
+
+ public static void Type (params object[] vals) {
+ Console.Write (ListToString (vals, 2, false));
+ }
+
+ public static void Show (params object[] vals) {
+ Console.WriteLine (ListToString (vals, 1, true));
+ }
+
+ // Math
+
+ [DefaultArgumentCount (2)]
+ public static double Sum (params double[] vals) {
+ double sum = 0;
+ foreach (double val in vals)
+ sum += val;
+
+ return sum;
+ }
+
+ public static double Minus (double val) {
+ return -val;
+ }
+
+ // Variables
+ [PassContext]
+ public static void Make (LogoContext context, string variable, object value) {
+ if (!context.Dict.Contains (variable)) {
+ context = context.RootContext;
+ }
+
+ context.Dict[variable] = value;
+ }
+
+ [PassContext]
+ public static void LocalMake (LogoContext context, string variable, object value) {
+ context.Dict[variable] = value;
+ }
+
+ [PassContext]
+ public static void Local (LogoContext context, string variable) {
+ context.Dict[variable] = LogoContext.NullVariable;
+ }
+
+ [PassContext]
+ public static void Local (LogoContext context, ICollection variables) {
+ foreach (string variable in variables) {
+ context.Dict[variable] = LogoContext.NullVariable;
+ }
+ }
+
+ [PassContext]
+ public static object Thing (LogoContext context, string variable) {
+ return context.Dict[variable];
+ }
+
+ // Workspace
+ public static void Bye () {
+ System.Environment.Exit (0);
+ }
+
+ // Flow control
+ [PassContext]
+ public static void Output (LogoContext context, object val) {
+ context.Output (val);
+ }
+
+ [PassContext]
+ public static object Run (LogoContext context, ICollection runlist) {
+ return Interpreter.Execute (context, runlist);
+ }
+ }
+}
+
View
13 MonoLOGO/Mono.Languages.Logo/Mono.Languages.Logo.Runtime/IMessageStore.cs
@@ -0,0 +1,13 @@
+namespace Mono.Languages.Logo.Runtime {
+
+ public interface IMessageStore {
+
+ bool SupportsMessage (string message);
+ MessageInfo DescribeMessage (string message);