diff --git a/README b/README index 10ab5df..96fe515 100644 --- a/README +++ b/README @@ -1,8 +1,16 @@ -Partcl - a NQP-based implementation of Tcl +partcl-nqp -This is a proof of concept to reimplement partcl (tcl on parrot) using -the latest compiler tools available for parrot. +Tcl 8.5 on the parrot VM. This does not use the tcl C library, but is a from- +scratch implementation using the Parrot Compiler Toolkit. + +"nqp" in the name comes from the "nqp-rx" toolkit. NQP is Not Quite Perl 6, +and is a mini language that is much higher level than PIR. It also provides +a nice interface to writing mini languages, making it much easier to implement +the various mini languages inside tcl (globbing, regexen, binary) See docs/todo.pod for a list of known issues. See docs/overview.pod for information on how this version works. + +See http://github.com/partcl/partcl for the original non-PCT version that +is more complete, but is only maintained to keep current with parrot changes. diff --git a/docs/overview.pod b/docs/overview.pod index 70f3df4..517b630 100644 --- a/docs/overview.pod +++ b/docs/overview.pod @@ -2,25 +2,26 @@ partcl-nqp is a tcl 8.5 compiler for the PVM (Parrot Virtual Machine). -It uses the Parrot Compiler Toolkit (NQP-RX, HLL::Compiler) to generate +It uses the Parrot Compiler Toolkit (nqp-rx, HLL::Compiler) to generate PIR (Parrot Assembly), which is then compiled to PBC (Parrot Bytecode), -which is then bundled into a "fakecutable". +which is then bundled into a "fakecutable". The fakecutable contains the +bytecode, and enough C to invoke the VM. It is NOT a JITted version. -=head1 Architecture +=head1 Languages partcl-nqp is written primarily in NQP (Not Quite Perl 6; specifically -NQP-R), with some PIR. +nqp-rx), with as little PIR as we can manager. =head2 Grammars and Actions There are several Perl 6 Grammars in F; Partcl contains the main language, src/ARE is the standard tcl regexes, etc. -Each Grammar.pm file contains the rules (See Perl 6's Synopsis 5) for -parsing that mini language. The Actions.pm file contains instructions to +Each F file contains the rules (See Perl 6's Synopsis 5) for +parsing that mini language. The F file contains instructions to convert the parse into parrot's AST (Abstract Syntax Tree). -The small Compiler.pm for each mini language takes advantage of the parrot +The small F for each mini language takes advantage of the parrot library to convert the AST to an OST (opcode syntax tree), which is then converted to PIR, and finally PBC. @@ -96,10 +97,9 @@ tests in this directory as a prelude to running the spec tests. =head1 Alternate history -There is a version of partcl written using PGE & TGE. That version has +There is a version of partcl written using C & C. That version has no active development but is maintained minimally so it compiles with the latest version of parrot. Much of I version includes hand-translated NQP based on the PIR from that version. =cut - diff --git a/src/Partcl/commands/namespace.pm b/src/Partcl/commands/namespace.pm index 35a89fc..a993406 100644 --- a/src/Partcl/commands/namespace.pm +++ b/src/Partcl/commands/namespace.pm @@ -1,50 +1,175 @@ our sub namespace(*@args) { - if +@args < 1 { + Namespace::dispatch_command(|@args); +} + +module Namespace; + +our %Arg_limits; +our %funcs; +our %Auto_vivify; + +INIT { + + ## Negative limit in "max" position => unlimited. + %funcs := Namespace::children; + %Arg_limits := [ 0, 2, "?name? ?pattern?" ]; + + %funcs := Namespace::code; + %Arg_limits := [ 1, 1, "script" ]; + + %funcs := Namespace::current; + %Arg_limits := [ 0, 0, "" ]; + + %funcs := Namespace::delete; + %Arg_limits := [ 0, -1, "" ]; + + %funcs := Namespace::ensemble; + %Arg_limits := [ 1, 0, "subcommand ?arg...?" ]; + + %funcs := Namespace::eval; + %Arg_limits := [ 2, -1, "name arg ?arg...?" ]; + + %funcs := Namespace::exists; + %Arg_limits := [ 1, 1, "name" ]; + + %funcs := Namespace::export; + %Arg_limits := [ 0, 0, "namespace" ]; + + %funcs := Namespace::forget; + %Arg_limits := [ 0, 0, "namespace" ]; + + %funcs := Namespace::import; + %Arg_limits := [ 0, -1, "namespace" ]; + + %funcs := Namespace::inscope; + %Arg_limits := [ 0, 0, "namespace" ]; + + %funcs := Namespace::origin; + %Arg_limits := [ 0, 0, "namespace" ]; + + %funcs := Namespace::parent; + %Arg_limits := [ 0, 1, "?name?" ]; + + %funcs := Namespace::path; + %Arg_limits := [ 0, 1, "namespaceList" ]; + + %funcs := Namespace::qualifiers; + %Arg_limits := [ 1, 1, "string" ]; + + %funcs := Namespace::tail; + %Arg_limits := [ 1, 1, "string" ]; + + %funcs := Namespace::upvar; + %Arg_limits := [ 0, 0, "namespace" ]; + + %funcs := Namespace::unknown; + %Arg_limits := [ 0, 0, "namespace" ]; + + %funcs := Namespace::unknown; + %Arg_limits := [ 0, 0, "namespace" ]; + + %funcs := Namespace::which; + %Arg_limits := [ 0, 0, "namespace" ]; +} + +# Parses optional -args, and generates "wrong#args" errors +# Dispatches to fairly normal NQP subs for the detailed work. +our sub dispatch_command(*@args) { + my $num_args := +@args -1 ; # need option + + if $num_args < 0 { error('wrong # args: should be "namespace subcommand ?arg ...?"'); } my @opts := ; - my $cmd := _tcl::select_option(@opts, @args.shift() ); - - if $cmd eq 'children' { - return ''; - } elsif $cmd eq 'code' { - return ''; - } elsif $cmd eq 'current' { - return ''; - } elsif $cmd eq 'delete' { - return ''; - } elsif $cmd eq 'ensemble' { - return ''; - } elsif $cmd eq 'eval' { - return ''; - } elsif $cmd eq 'exists' { - return ''; - } elsif $cmd eq 'export' { - return ''; - } elsif $cmd eq 'forget' { - return ''; - } elsif $cmd eq 'import' { - return ''; - } elsif $cmd eq 'inscope' { - return ''; - } elsif $cmd eq 'origin' { - return ''; - } elsif $cmd eq 'parent' { - return ''; - } elsif $cmd eq 'path' { - return ''; - } elsif $cmd eq 'qualifiers' { - return ''; - } elsif $cmd eq 'tail' { - return ''; - } elsif $cmd eq 'upvar' { - return ''; - } elsif $cmd eq 'unknkown' { - return ''; - } elsif $cmd eq 'which' { - return ''; + my $cmd := _tcl::select_option(@opts, @args.shift, 'option'); + + my @limits := %Arg_limits{$cmd}; + + if (@limits[1] >= 0 && $num_args > @limits[1]) || $num_args < @limits[0] { + my $msg := @limits[2]; + $msg := " $msg" unless $msg eq ''; + error("wrong # args: should be \"namespace $cmd$msg\"") } + + my &subcommand := %funcs{$cmd}; + &subcommand(|@args); } +my sub children(*@args) { + ''; +} + +my sub code(*@args) { + ''; +} + +my sub current(*@args) { + ''; +} + +my sub delete(*@args) { + ''; +} + +my sub ensemble(*@args) { + ''; +} + +my sub eval(*@args) { + ''; +} + +my sub exists(*@args) { + ''; +} + +my sub export(*@args) { + ''; +} + +my sub forget(*@args) { + ''; +} + +my sub import(*@args) { + ''; +} + +my sub inscope(*@args) { + ''; +} + +my sub origin(*@args) { + ''; +} + +my sub parent(*@args) { + ''; +} + +my sub path(*@args) { + ''; +} + +my sub qualifiers(*@args) { + ''; +} + +my sub tail(*@args) { + ''; +} + +my sub upvar(*@args) { + ''; +} + +my sub unknown(*@args) { + ''; +} + +my sub which(*@args) { + ''; +} + # vim: filetype=perl6: diff --git a/t/cmd_namespace.t b/t/cmd_namespace.t index 6e78fb6..5e76d12 100755 --- a/t/cmd_namespace.t +++ b/t/cmd_namespace.t @@ -14,7 +14,7 @@ eval_is {namespace asdf} \ eval_is {namespace children a b c} \ {wrong # args: should be "namespace children ?name? ?pattern?"} \ - {namespace children: too many args} {TODO NQPRX} + {namespace children: too many args} eval_is {namespace children what?} \ {namespace "what?" not found in "::"} \ @@ -38,11 +38,11 @@ is [namespace eval ::audreyt {namespace children}] ::audreyt::Matt \ eval_is {namespace qualifiers} \ {wrong # args: should be "namespace qualifiers string"} \ - {namespace qualifiers: no args} {TODO NQPRX} + {namespace qualifiers: no args} eval_is {namespace qualifiers string string} \ {wrong # args: should be "namespace qualifiers string"} \ - {namespace qualifiers: too many args} {TODO NQPRX} + {namespace qualifiers: too many args} is [namespace qualifiers ::a::b::c] ::a::b {namespace qualifiers: simple} {TODO NQPRX} is [namespace qualifiers :::a:::b::c] :::a:::b {namespace qualifiers: extra colons} {TODO NQPRX} @@ -50,11 +50,11 @@ is [namespace qualifiers :::a:::b::c] :::a:::b {namespace qualifiers: extra colo eval_is {namespace tail} \ {wrong # args: should be "namespace tail string"} \ - {namespace tail: no args} {TODO NQPRX} + {namespace tail: no args} eval_is {namespace tail string string} \ {wrong # args: should be "namespace tail string"} \ - {namespace tail: too many args} {TODO NQPRX} + {namespace tail: too many args} is [namespace tail ::] {} {namespace tail: main} is [namespace tail {}] {} {namespace tail: empty} @@ -64,11 +64,11 @@ is [namespace tail :::foo:::bar:::baz] baz {namespace tail: extra colons} {TODO eval_is {namespace exists} \ {wrong # args: should be "namespace exists name"} \ - {namespace exists: no args} {TODO NQPRX} + {namespace exists: no args} eval_is {namespace exists a a} \ {wrong # args: should be "namespace exists name"} \ - {namespace exists: too many args} {TODO NQPRX} + {namespace exists: too many args} eval_is {namespace exists a} 0 {namespace exists: failure} {TODO NQPRX} is [namespace exists {}] 1 {namespace exists: global implicit} {TODO NQPRX} @@ -77,7 +77,7 @@ is [namespace exists ::] 1 {namespace exists: global explicit} {TODO NQPRX} eval_is {namespace eval foo} \ {wrong # args: should be "namespace eval name arg ?arg...?"} \ - {namespace eval: too few args} {TODO NQPRX} + {namespace eval: too few args} namespace eval foo { proc bar {} {return ok} @@ -108,7 +108,7 @@ eval_is {namespace exists foo} 0 {namespace delete} {TODO NQPRX} eval_is {namespace current foo} \ {wrong # args: should be "namespace current"} \ - {namespace current: too many args} {TODO NQPRX} + {namespace current: too many args} is [namespace current] :: {namespace current: global} {TODO NQPRX} is [namespace eval foo {namespace current}] ::foo {namespace current: ::foo} {TODO NQPRX} @@ -116,7 +116,7 @@ is [namespace eval foo {namespace current}] ::foo {namespace current: ::foo} {TO eval_is {namespace parent foo bar} \ {wrong # args: should be "namespace parent ?name?"} \ - {namespace parent: too many args} {TODO NQPRX} + {namespace parent: too many args} is [namespace parent ""] {} {namespace parent: ::} is [namespace parent foo] :: {namespace parent: ::foo (explicit)} {TODO NQPRX}