Anonymous committed db6bc97 Draft

Initial import of 'N-DCNC version 1.0 revision 2000.0808 sources.

Comments (0)

Files changed (12)

+                               'N-DCNC
+                               -------
+                 The Official Language of Pride and Envy
+                 ---------------------------------------
+Last updated Aug 8 2000 Chris Pressey, Cat's Eye Technologies
+What is 'N-DCNC?
+Besides just tasting good when served with crackers and white wine,
+'N-DCNC is a computer programming language as well.
+'N-DCNC provides the programmer with sophisticated features such
+as subtraction, bodaceous syntax elements such as infix operators,
+powerful abstractions such as single-character variable names, and
+groundbreakingly radical concepts such as side-effects.
+Warning and History
+'N-DCNC was reverse-engineered from spaceflight control systems
+found aboard crashed extraterrestrial vehicles.  It was related
+first-hand to yours truly by a shifty figure in a trenchcoat
+known to me only as "Deep Copy".  Over coffee and doughnuts at a
+local Tim Horton's, he described in hushed tones the following
+language, claiming that he was part of the engineering team that
+was subcontracted for the purpose of deciphering it.
+As such, if you choose to use the 'N-DCNC language, I cannot be
+not held responsible should various shadowy agents force themselves
+into your home and erase all your computer files, OK?  Good.
+There is also a strong, but hitherto unrealized connection between
+this language and manufactured glam pop bands.  For example,
+'N-DCNC does not write it's own music nor play it's own instruments.
+It has been known to lip-synch to a pre-recorded soundtrack.
+The Structure of an 'N-DCNC Program
+An 'N-DCNC program consists of one big expression.  Save those
+semicolons; you won't need them here!
+An expression contains many primitive terms connected by infix
+operators.  There are as many levels of precedence as there are
+operators, one on each level.  The precedence of an operator
+depends on it's position in the ASCII table; lower ASCII values
+means lower precedence (isn't that *much* easier to remember?)
+The infix operators are (from lowest to highest precedence:)
+  *     Wally     likes cats & bunnies    multiply/loop
+  +     Bill      shy but deep            add
+  ,     Chaz      enjoys parties          input/output
+  -     Jon       a real heartbreaker     subtract
+  .     Petrov    provably happy          assignment
+  /     DIV       enjoys decision-making  int-divide/if
+A sub-expression enclosed in parentheses like so (1+2) has
+a higher precedence than the entire expression it occurs in
+(as foreign and unnatural as this may seem, it's true...)
+Terms are pretty boring, but let's examine them anyway.
+The symbols
+  A 2 3 4 5 6 7 8 9 J Q K
+represent the integers from one to twelve.  The symbol A
+represents thirteen instead of one when aces are high.
+Aces are only high in certain restricted situations, such
+as when the compiler mistakenly assumes they are high.
+To represent zero, you, the programmer, must use 7-7 or
+anything of a similar nature.
+Imperative Programming Becomes Possible
+Lower-case letters represent variables.  Well, kind of.
+In fact, the variables aren't often too happy with the
+respresentation they get from their elected lower-case
+letters, and see them as trough-feeding, self-serving,
+two-faced, and devoid of moral fibre.
+You can assign to a variable with something like Z.Q
+To increment or decrement a variable try Z.(z+A) or Z.(z-A)
+  It turns out Deep Copy gave me the wrong impression,
+  here; I thought he meant that lower-case letters were
+  rvalue-type variables and upper-case letters were their
+  lvalue-type equivalents.  As it turns out, this is only
+  one possible interpretation.  The notation that seems
+  to actually have been used is closer to `z for an lvalue.
+Try to avoid letters from the start of the alphabet
+(a,b,c,d,e,f...) because they're 'taboo': likely used
+for other internal purposes (as sad as that is.)
+Not much need to explain addition and subtraction,
+except perhaps to those who do not already grok such
+concepts; if you are a member of this set, seriously
+consider a course on remedial arithmetic.
+But the other operators need some explanation, because
+they tend to stray from the laws of computer programming,
+if not the laws of physics themselves.  Well, no, OK,
+just the first one, and yes, I know, there are no "laws"
+when it comes to computer programming, but, so, well,
+er, ...
+Anyway, multiplication is defined thus, in some fictional
+pseudocode language (which is not included with 'N-DCNC):
+mul(by-value int a, by-name int b) =
+  c = 0;
+  while a > 0
+  {
+    c = c + do(b); a--;
+  }
+  c;
+Or, to say it in PortableFalse:
+  [b:a:0c:[a;0>][c;b;!+c:a;1-a:]#c;]e:
+Note that b is an expression instead of a simple value.
+Unlike other values it is passed as a 'thunk' - a parameterless
+function.  Multiplication does not automatically evaluate the
+thunk that is b; a has to be greater than zero at some point.
+This is why we have normal-order evaluation instead of
+eager evaluation - so that multiplication can cause side
+effects that are our loops that let us do all that neat
+solving-any-problem stuff, availability of half-infinite
+lengths of tape notwithstanding.
+So if we say
+  K*(7,A-A)
+What we will get on the standard output is 12 BELs.
+(But how do we know whether it is noon or midnight?
+Look at the sky - if there's a big ball of fire up there,
+it's noon.)
+By changing the a variable in the loop (it's a global
+variable after all,) you can theoretically cause the loop
+to never terminate, or terminate based on some magical
+condition. (That is, iff magical conditions are locally
+defined to be synonymous with logical conditions for the
+purposes of the previous sentence.)
+Division has a similar relationship with the simple
+and super-common 'if' statement.  In a division by zero,
+the numerator's thunk isn't evaluated.  But in division
+by one or anything else, it is.
+Again with the fictional pseudocode (sold seperately,
+may not be exactly as illustrated):
+div(by-name int a, by-value int b) =
+  if (b = 0)
+  {
+    0;
+  }
+  do(a) / b;
+In PortableFalse:
+  [\b:a:b;[a;!b;/]?b;~[0]?]d:
+Summary and Closing Arguments
+One day all computer programmers will be replaced by robots,
+and they'll all code in 'N-DCNC.  But this will only be possible
+on new, extremely large (and noisy) machines using a strange new
+technology called 'relays'.  These new 'super-'computers will be
+so large and expensive that only the five richest software
+companies will be able to afford to automate their programming
+department.  The rest will probably continue to use the present-
+day software engineering model, that is, obtaining galleys full
+of slaves, releasing the code they come up with to the customer
+as a finished product, then "supporting it into existance" as
+the customer whines and bitches about how their system doesn't
+work the way they or any sane person would expect it to.
+Appendix 7: EBNF Grammar for 'N-DCNC
+'N-DCNC := E(0).
+E(n)    := E(n+1) {O(n) E(n+1)}.
+Prim    := "(" E(0) ")" | Digit | ["`"] Var.
+Digit   := one of "A23456789JQK".
+Var     := one of "abcdefghijklmnopqrstuvwxyz".
+O = ('*', '+', ',', '-', '.', '/').
+E(6) = Prim.
+Appendix 22: About the 'N-DCNC Compilers
+Both 'N-DCNC compilers compile 100% pure 'N-DCNC code to Wouter
+van Oortmerssen's False language (actually, his PortableFalse
+"100% pure" means that the input code contains no syntax errors,
+because neither compiler goes out of it's way to bother with such
+irrelevant trivia.  Dammit Jim, they're compilers, not proofreaders.
+False and PortableFalse are trademarks of $#%!
+'N-DCNC is not a trademark of anything; in fact, I'm pretty sure
+'N-DCNC and its compilers are a mere hallucination.  Hmm...
+DISCLAIMER: 'N-DCNC and its compilers are a mere hallucination.
+Therefore I cannot be held responsible for anything they may
+or may not do or appear to do.
+Aggregation of false.c into this package as an easement for
+playing with 'N-DCNC will probably be construed by Wouter as a
+hostile intellectual-property manouevre to subvert his FALSE
+dynasty.  He'll be siccing his army of lawyers on me in a matter
+of hours I'm sure.  So enjoy 'N-DCNC while it remains legally
+feasible to do so.
+* '
+  Written in only slightly obfuscated Perl, this compiler (mostly)
+  works.
+* '
+  [This doesn't exist yet.  I've tried four times and decided I had
+  better take a long break (like, at least a week or two) before
+  trying again.  I've come to realize that, despite having invented
+  the language, I'm a terrible Befunge programmer.  My mistake here
+  is probably trying to squash it too much.  Still, I wanted to get
+  SOMETHING out the door for the Essies, early, just in case.]
+Appendix 22a: About the Compile Cycle
+Mainly about ' [which doesn't exist yet, but see the last
+three attempts,] but mostly applies to ' as well.
+We store a stack called the 'call stack' on the 0'th row of
+space (0,0)-(79,0) or even further in Befunge-97 or Perl.
+The pointer to the top of this stack is stored at (0, 1).
+We store the last token read at (1, 1).  So the program looks like:
+where the program itself begins at >.  The first c contains a v,
+and t contains a space, both of which will be overwritten by the
+startup code.  We'll use (2, 1), (3, 1) for other scratch variables
+if the need arises.
+(4, 1) and on are 4-cell chunks of output boilerplate in
+PortableFalse used by the gencode routine, a reference to which
+is made below.
+Speaking of which, the startup code @ (0, 2) consists of:
+- writing a 0 into t
+- dumping the PortableFalse runtime library for 'N-DCNC to stdout
+- pushing an 0 (OUT) onto the call stack
+- scanning the first token into k
+There is then a main parse loop @ (0, 5), which consists of:
+- Is the TOS > 5, that is, have we recursed down through all the
+  available infix operators, and should we look for terms now?
+- If so, we check k for an open paren.  If found it indicates there
+  is a sub-expression.  We scan a new symbol into k, push 1 (NEST)
+  onto the call stack, push a zero onto the stack, and go back to
+  the start of the main parse loop.
+- If there's no open paren, we check for 2-9 or J or Q or K or A and
+  if so, generate a constant.  Or, we check for a-z and generate a
+  variable access.  In both cases we simply scan for new tokens
+  and fall through to the 'common tail', described below.
+- On the other hand, what if the TOS is <= 5?  Well, we push 2
+  (LHS) onto the call stack.  We also duplicate the TOS, increment
+  it, and jump back to the beginning of the main parse loop.
+We also have a 'common tail' @ (??, ??), which consists of
+some code and then an 'on goto' type branch:
+- discard the top stack element
+- pop the call stack into a temporary variable and
+  jump based on it's value, which may be OUT, NEST, LHS, or RHS:
+  0 OUT: jump to the end of the translation logic; print the
+         PortableFalse postlude (currently just a '%') and exit.
+  1 NEST: scan a token and fall through to the common tail (again.)
+  2 LHS: if the current token is not equal to the value on the
+         top of the stack plus '*', fall through to the common tail.
+         If it is, print a '[' if the TOS is 0 or 5 (to lazy-ize
+         the parameters), scan another token, push 3 (RHS) onto
+         the call stack, increment the top of the stack and go
+         back to the start of the main parse loop.
+  3 RHS: based on the top of the stack, print out a snippet of
+         PortableFalse code based on the current operator, then
+         fall through to LHS.
+And that's basically it.  Easy, really.  That's what a recursive
+descent parser looks like when you don't use recursion, or well,
+you don't use any built-in call/return/function mechanism at all
+because there essentially isn't any...
+Appendix 22q. Befunge Idioms
+  ~11p is scan a token
+  11g is get current token
+  01g      is get the call stack ptr (an x coordinate)
+  ?01p     is set the call stack ptr
+  01g1+01p is increment the call stack ptr
+  01g1-01p is decrement the call stack ptr
+  01g0g    is get the value on the top of the call stack
+  ?01g0p   is set the value on the top of the call stack
+  01g1-:01p0g       is pop the call stack
+  ?01g0p01g1+01p    is push onto call stack
+Appendix 3. Excerpts from the Author's 'N-DCNC Diary
+May 12 2000.  Met a man who told me to call him "Deep Copy."  Not
+really a pleasant guy.  But he seems interested in language design.
+June 7 2000.  Deep Copy told me about a language he has access to
+the specifications for.  Claims it was reverse-engineered from
+spaceflight control systems found aboard crashed flying saucers.
+He told me not to write anything he talked about down, but he knew
+full well who I was and what I do so I assumed he had to be lying.
+Or stupid.  If he didn't want me to write it down, he shouldn't
+have told me.
+July 26 2000.  Got a rough version of 'N-DCNC working and decided
+it would really piss Deep Copy off if I submitted it for an
+Esoteric Award...
+August 8 2000.  Got a phone call from Deep Copy today.  Somehow he
+had found out about 'N-DCNC being an Essy entry.  Also faxed over
+some corrections along with a note about how my life could be in
+jeopardy if I continued to pursue my interests in these
+"Un-Canadian Activities". (???)
+Glossary of Terms
+- Dom-ain't: a corporation with a name like but
+  with a doman name like
+- Draffle: the little personal items (Dilbert cartoons,
+  fuzzy things with googly-eyes, etc) put in one's office or
+  workspace in a vain attempt to make it more familiar.
+- Meta-barber: the person who cuts your barber's hair.
+- Precipitation Limbo: where the rain goes when it's not
+  raining.
+- Taunt Marquee: the route-identifying sign in the rear
+  window of the bus you just missed.


+                         ^                         <          <
++                             >00g"("-#v_~00p"N"101gp01g1+01p0^
+-                             v        <
+*                             >00g"?"-#v_~00p"&",        00g,~00pv
+/                             v        <
+$                             >00g,                          ~00pv
+                         ^                           <
+>    :2+0\g00g-#v_:4-#v_"{",v
+                      >     >~00p"R"101gp01g1+01p:1+ ^
+                >                     v
+#    :4-#v_"}",>:2+0\g,               v>
+         >     ^
+^ #                  <
+  v                                   <                          <
+  >$01g1-01p101ggv
+  v              <
+  >:"L"-#v_$         ^
+  v      <
+  >:"R"-#v_$                           ^
+  v      <
+  >:"N"-#@_$                  ~00p    ^


+  **]e;!+   %,0 -   f;! ]d;!
+>"];c:\:c$[    ">:#,_01g0p01g1+01p~11pv
+v                                     <
+^    >11g"("-#v_~11p101g0p01g1+01p
+ v >,~11pv    >11g"1"`#v_>      >11g,
+  "a"11g`#v_v>11g,";",v>"9"11g`#^_ 
+ v #      ># ^#   p11~<       >:1+4*:1v       
+ >$01g1-:01p0g:#v_:1-#^_:2-#v_^v1+1:,g<
+ ^ #    $<@, "%"<v --"*"g11:<  >g,:2+1v
+ ^v^":",g11$<    ># _v      ^ ,g1+3:,g<
+^ >:#v_:5-#v_   >~11p 301g0p01g1+01p1+
+ ^   >     >"[",^    >


+  **]e;!+   %,0 -   f;! ]d;!
+<             +1p10+1g10p0g102_v#!`5:<
+v_v#      -"A"g11_v#      -"(":<>$#<$^
+  >"1",  v        >~11p101g0p01g1+01p^
+>11g"J"-!#v_11g"Q"-!#v_11g"K"-!#v_1$ v
+ v_v#`$<<v,g11_v#`g11 ":"_v#`"1"  g11<
+     p11~<>"01" v"12"<   >>      ~11pv
+  <    ^ g11"`"<>,,      ^,,"31"<  ^
+ >  11g" "-,":",                 ~11pv
+   >11g,";",                     ~11pv
+  #      v  p11~<@,"%"<>
+^        <>:"*"+11g-  #^_:#v_        v
+ > g,:1+1g,:2+1g,:3+1g,$ v >:5-#v_   v
+  ^       #+1:p10+1g10p0g103p11~<,"["<
+          ^             $<


+  **]e;!+   %,0 -   f;! ]d;!
+<            +1:p10+1g10p0g102_v#!`5:<
+ 0p10+1g10p0g101p11~_v#!-"("g11<     ^
+v                    <
+>11g"1"`!#v_":"11g`!#v_11g," ",v
+vp11~     <  <       >#<      #< <   v
+ v  g11_v#-"K"g11_v#-"Q"g11_v#-"J"g11<
+ >"A"-#v _1, #v        #         #
+        >93+,^<   >92+,^    >91+,^
+       >11g"`"`#v_11g" "-,":",   ^
+                > 11g,";",       ^
+>$01g1-:01p0g:1-!#v_:! #v_:2-!#v_ gencode
+^             p11~<@,"%"<
+                         lhs   <
+/* Introducing: Portable False!!!!
+   PortableFalse is different from AmigaFalse in:
+   - its Portable!!! :-)
+   - full stack checking
+   - strongly typed (no joke, really!)
+   - debug-modi
+   - real and meaningfull errormessages
+   - ` inline assembly not supported
+   - : and ; not supported for other than variable access.
+   - "beta" (flush) and "zero-slash" (pick) from the amiga charset
+     are now 'B' and 'O' resp.
+   - 'D' toggles stack-watch mode on and off. format:
+     [ bottom_of_stack , ... , top_of_stack | next_symbol ]
+   - "-q" on command line is quiet mode: no title printing.
+     (usefull for "filter"-type programs: 1> False -q filter.f <bla >burp)
+   this source has been writtin in good C style:
+   - no modularity whatsoever (only main())
+   - only global variables
+   - lots of ugly macros (replacing functions)
+   - great source formatting and indentation
+   still it compiles on 4-5 different ansi-C compilers. if you have trouble
+   porting it to your machine, your compiler sucks. (guaranteed to be
+   digested by: MaxonC++, SAS/C, DICE, GNUC++ (also on other platforms))
+   todo:
+   - interactive debugging?
+   False, Amiga False, Portable False are all trademarks of $#%!
+#define MZ 10000
+#define MS 1000
+#include <stdio.h>
+#define NIL 0
+#define NUM 0
+#define FUNC 1
+#define VADR 2
+#define UNDEF 3
+#define l(x) ;break;case x:
+#define x(num) {ernum=num;goto er;}
+#define push(v,a) {if(S-2<sbeg)x(4)else{*--S=(v);*--S=(X)a;};}
+#define pop(v,a) {if(S+2>se)x(5)else{if((ex=(int)a)!=(ge=(int)*S++))x(6);\
+v= *S++;};}
+#define pa(v,av) {if(S+2>se)x(5)else{av= *S++;v= *S++;};}
+#define ru(v) {if(rp-1<rbeg)x(13)else{*--rp=(v);};}
+#define ro(v) {if(rp+1>rend)x(14)else{v= *rp++;};}
+#define CA(c) {ru(p);p=c;}
+#define pu(x) push(x,NUM)
+#define po(x) pop(x,NUM)
+#define op(o) {po(b)po(d);pu((X)((int)d o (int)b));}
+#define cm(o) {po(b)po(d);pu((X)(-((int)d o (int)b)));}
+#define un(o) {po(b)pu((X)(o (int)b));}
+#define ne (p<end)
+#define W while
+#define ec {W((*p!='}')&&ne)p++;p++;if(!ne)x(10);}
+#define P printf
+typedef char*X;typedef char**XP;X ST[MS],RST[MS],var[52],b,d,e,f,t1,t2,t3;
+XP sbeg=ST+12,se=ST+MS-12,S,ts,rbeg=RST+12,rend=RST+MS-12,rp,vp;int ernum=
+0,t,db=0,ex,ge,qq;FILE*fh;char src[MZ+5],a,c=0,*s,*end,*beg,*p=0,*erstr[]=
+{"no args","could not open source file","source too large","data stack ov"
+"erflow","data stack underflow","type conflict","stack not empty at exit "
+"of program","unknown symbol","portable inline assembly not available","u"
+"nbalanced '{'","unbalanced '\"'","unbalanced '['","return stack overflow"
+,"return stack underflow"},*types[]={"Integer","Functional","Variabele",""
+"Unitialised"};int main(int narg,char*args[]){S=se;rp=rend;t=1;for(vp=var;
+'q')t=2;if(t==1)P("Portable False Interpreter/Debugger v0.1 (c) 1993 $#%!"
+++='\n';fclose(fh);end=s-1;beg=src+1;p=beg;W(ne){c= *p++;if(c>='0'&&c<='9'
+){int num;sscanf(p-1,"%d",&num);W((*p>='0')&&(*p<='9'))p++;push((X)num,NUM
+);}else if(c>='a'&&c<='z'){push((X)&var[(c-'a')*2],VADR);}else switch(c){
+case' ':case '\n':case'\t':l('+')op(+)l('-')op(-)l('*')op(*)l('/')op(/)l(
+S+((t=(int)b*2)+2)>se)x(5)b= *(S+t);d= *(S+t+1);push(d,b)l(':')pop(b,VADR)
+l('D')db=!db;l('[')push((X)p,FUNC)t=1;W(t>0&&ne){a= *p++;if(a=='['){t++;}
+else if(a==']'){t--;}else if(a=='{'){ec}else if(a=='\"'){W((*p!='\"')&&ne)
+if((int)b){ro(d)ru(d)CA(d)ru((X)1);}else{ro(d)ro(d);};}else if((int)e==1){
+ru(b);CA(d)ru((X)0);break;default:x(8);};if(db){c= *p;if(c!=' '&&c!='\n'&&
+ts-2);if(t==FUNC){P("<func>");}else if(t==VADR){P("<var>");}else P("%d",(
+)x(7);er:if(ernum){P("\nERROR: %s!\n",erstr[ernum-1]);if(c)P("WORD:  '%c'"
+"\n",c);if(ernum==6)P("INFO:  Expecting %s type, while reading %s type.\n"
+'\n'){end++;};t=end-beg;*end=0;if(t>0){P("LINE:  %s\n",beg);qq=p-beg+3;P(
+"AT:");for(t=0;t<qq;t++){putchar(' ');};P("^\n");};};}return 0;}
+  **]e;!+   %,0 -   f;! ]d;!
+>:5`#v_:1+201g0p01g1+01p             >
+     >"@"11g-#v_~11p101g0p01g1+01p0  ^
+#!/usr/local/bin/perl -w
+# ' - a 'N-DCNC to PortableFalse compiler in Perl
+# v2000.08.12 Chris Pressey, Cat's Eye Technologies
+$token = '';
+sub scan
+  exit(0) if not read(STDIN, $token, 1);
+sub top
+  return $_[$#_];
+# print 'D';
+print '[\b:a:b;[a;!b;/]?b;~[0]?]d:';
+print "\n";
+print '[b:a:0c:[a;0>][c;b;!+c:a;1-a:]#c;]e:';
+print "\n";
+push @back, 'Out';
+push @stack, 0;
+  if (top(@stack) > 5)
+  {
+    if ($token eq '@')
+    {
+      scan();
+      push @back, 'Nest';
+      push @stack, 0;
+      goto e;
+      scan();
+    }
+    elsif ($token =~ /^[AJQK23456789]$/)
+    {
+      $token = 1  if $token eq 'A';
+      $token = 10 if $token eq 'J';
+      $token = 11 if $token eq 'Q';
+      $token = 12 if $token eq 'K';
+      print "$token ";
+      scan();
+    }
+    elsif ($token eq '`')
+    {
+      scan();
+      print "$token;";
+      scan();
+    }
+    else
+    {
+      print $token;
+      scan();
+    }
+  } else
+  {
+    push @back, 'LHS';
+    push @stack, top(@stack)+1;
+    goto e;
+    if($token eq chr(top(@stack)+ord('*')))
+    {
+      if(top(@stack) == 0) { print '['; }
+      if(top(@stack) == 5) { print '['; }
+      scan();
+      push @back, 'RHS';
+      push @stack, top(@stack)+1;
+      goto e;
+      print ']e;!' if top(@stack) == 0;
+      print '+'    if top(@stack) == 1;
+      print '%,0'  if top(@stack) == 2;
+      print '-'    if top(@stack) == 3;
+      print '$c:\:c;' if top(@stack) == 4;
+      print ']d;!' if top(@stack) == 5;
+      goto LHS;
+    }
+  }
+  pop @stack;
+  my $b = pop @back;
+  goto LHS if $b eq 'LHS';
+  goto RHS if $b eq 'RHS';
+  goto Nest  if $b eq 'Nest';
+print '%';