1.1.0 • Published 7 years ago

plocarf v1.1.0

Weekly downloads
3
License
Unlicense
Repository
-
Last release
7 years ago
PLOCARF (Programming Language Of Classes And Restricted Functions) is a
programming language that can be made restricted for some application and
then compiled into a JavaScript code (and later, possibly others too, even
with programs that don't use JavaScript).

This program is public domain.


=== Functions ===

.Error(message,[lineNumber])
  A error subclass for PLOCARF compile errors. Instances of this class
  will have properties "plocarfMessage" and "plocarfLineNumber" to give
  information about the error.

.compatible(x,y,obj)
  Tells if type x and y are compatible, if the value is type x, and the
  expected type is type y. The third argument is an object whose "classes"
  property is an object with the PLOCARF classes to use during checking.

.compile(txt,opt)
  Compile a PLOCARF code given as the first argument. The second argument
  should be an object with the properties:

   .classes
     An object whose keys are PLOCARF class names and the values are the
     classes. Only own keys are used.

   .constants
     An object whose keys are constant names and whose values are the
     values of those constant (which must be a signed 32-bit integer).
     Only the own keys are used.

   .functions
     An object whose keys are PLOCARF global function names are the
     functions. Only own keys are used.

   .pool
     An array of initial pool strings. New pool strings can be added,
     which are given higher numbers than the strings in this pool. The
     initial pool is empty if not given.

   .traceFunction
     If given, will be called when compilation begins with a version of
     JavaScript's "Function" function (but of a different sandbox) and
     the return value is expected to be a function that will return the
     resulting function, in place of using Function to create it. You
     may use this to add in your own compilation or to display the
     JavaScript code that a PLOCARF function compiles into.

  The output is an object with properties:

    .classes
      An object whose keys are names of PLOCARF classes and whose values
      are those classes. The prototype is set to null.

    .functions
      An object whose keys are names of PLOCARF global functionss and
      whose values are those functions (which you can call just like
      JavaScript functions). The prototype is set to null.

    .pool
      The string pool (an array). This is a new array and does not modify
      the string pool array given for the input.

    .sandbox
      The contextified sandbox object.

.makeClass(cname,inherits)
  Make a non-root PLOCARF root class, with the given name and inheritance
  (the "prototype" and "types" properties automatically inherit it). The
  properties are the same as with .makeRootClass(), and the returned
  function does nothing if called.

.makeFunction(type,fun,[redefinable])
  Annotate a function fun with PLOCARF type information, and if
  redefinable is true, allows PLOCARF code to redefine it. This adds two
  properties named "type" and "redefinable" to the function. Return value
  is the function itself.

.makeRootClass(cname,[fun])
  Make a class suitable as a PLOCARF root class, with the given name (will
  be given to a "cname" property). If the second argument is given, it
  makes that function into a suitable PLOCARF root class; otherwise it
  returns a new function that does nothing. The returned function also has
  properties "inherits" (with value null), "prototype", and "types".

.makeUndefFunction(type)
  Similar to .makeFunction but automatically makes it redefinable and it
  throws an error if called. Must be redefined by the PLOCARF code.

.subset(x,y)
  Tells if the permission set x (as a string of sorted characters) is a
  (not necessarily strict) subset of the permission set y.

.typeEq(x,y)
  Tells if two types are equal (a deep compare of arrays).

.typeEq2(x,y)
  Tells if two types are equal, but considers an unrestricted numeric type
  to be equal to a numeric type with a restricted range.


=== Classes ===

A PLOCARF class is represented as a JavaScript function with the following
properties:

  .cname
    The PLOCARF class name.

  .inherits
    The class it inherits from (null if it is a root class).

  .locked
    If exists and true, this class may not be subclassed. Subclasses of
    existing subclasses are still possible if they aren't also locked.

  .prototype
    Has a "constructor" property which is this class itself, as well as
    other properties for any PLOCARF methods and constants. These names
    have a prefix: "F_" for methods, and "K_" for constants.

  .sealed
    If exists and true, no more properties may be added to this class.
    Subclasses and properties in the subclasses are still possible.

  .types
    Has the same names as the properties of the prototype (except
    constructor), but their values are types instead of defaults. In
    addition to methods and constants there are also the types of
    PLOCARF properties, which use a "P_" prefix. In the case of
    properties, the types may optionally have a property named "note"
    which is a index into the pool strings, and is the "note" that is
    applied to this property.

Both the .prototype and .types properties have a full prototype chain
for all classes they inherit from, and the root has null prototype.


=== Data types ===

%         ["%"]
  Boolean. Represented as a JavaScript boolean.

+         ["+"]
  Signed 32-bit integer. Represented as a JavaScript number.

n:n       ["+",n,n]
  Number within the given range (valid for properties and constants only).
  Represented same as the + type.

^         ["^"]
  Strings. Represented as a number which is an index into the string pool.

*t        ["*",t]
  List of values of type t. Represented as a JavaScript array of
  representations of type t. PLOCARF lists are considered immutable and
  JavaScript code should not alter their contents.

@c        ["@",c]
  Object of class c (or of any subclass). Represented as a JavaScript
  object or null.

#c        ["#",c]
  Subclass of class c. Represented as the function returned by the
  .makeClass() for that class.

&c        ["&",c]
  Subclass of class c and property values for it, except the properties
  that belong to class c itself. Represented as a JavaScript object.

c t       ["P",c,t]
  Name of type t property or method of class c (or a superclass).
  Represented as a string with the property or method name (including
  the prefix, if any).

(z)t$x$   ["F",[z],t,x]
  Function with arguments z with commas in between, each of which can be
  a name and colon and type, or a type by itself; t is the return type,
  and can be omitted if no return; x is the set of permissions, and $x$
  can be omitted for a pure function. Represented as a function. The
  array that represents the type specification does not include the names
  of the arguments to the function, but does include the types. Note that
  x in that array is a string, with the permissions in ASCII order.

!x        ["!",x]
  An opaque type. PLOCARF does nothing with values of such types except
  passing them unchanged, and checking that the type is correct.

none      ["."]
  When a . expression is used to represent a null pointer, this is the
  most general type of the expression; it becomes a @ type later. The
  representation is null.

none      ["?",f1,f2]
  A type usable as a function argument or function return value (for
  global functions only). See below section about custom function types.

none      ["V"]
  Only valid as the return type of a function. Indicates that there is no
  return value (in JavaScript it is the undefined value, but this is not
  guaranteed since a function that does return a value can be used too).


=== Custom function types ===

The type ["?",f1,f2] can be used as the type of arguments and/or return
value of host functions; this is like a kind of polymorphism. Cannot be
used in other cases such as a type of list elements or properties etc.

Arguments given to f1 (when annotating a function call):

- The annotated AST so far (an array; elements 2 and subsequent are the
arguments, where the "type" property of them are the annotated types;
element 1 is the AST for the expression evaluating to the function itself)

- The expected type of the return value

- The current index into the annotated AST array for this argument (will
be omitted if it is the return value)

The return value of f1 should be the type that this argument is expected
to be, or null if don't care, or a string if it is an error. It shouldn't
be null if it is the return value; it should be the actual return type.

Arguments given to f2 (when checking type compatibility):

- The function type to check compatibility with

- The argument or return type to check compatibility with

The return value of f2 should be true if it is OK or false otherwise.

If two function need compatible "?" types, then the array with the "?"
should be the same object (comparable by ===) in order to match.


=== Outer definitions ===

;
  No effect. You can add semicolons between definitions to avoid any
  ambiguity that may otherwise be involved. Adding multiple semicolons is
  also OK.

x:y{z}
  Make a new class named x which inherits from y and then z is the inner
  definitions for that class.

x+{y}
  Extend an existing class x with inner definitions y.

x y z
  Define a global function, where x is the name, y is the type, and z is
  the definition, which is one of: a {} statement, a semicolon by itself
  (the resulting function throws an error if called, but it can be
  redefined later with the same type; use this to forward declare), or a
  equal sign followed by a expression.

x=y
  Define a global constant/expression macro, named x, where y is an
  expression that the x is replaced by when later used in a expression.


=== Inner definitions ===

;
  No effect, like with outer definitions.

x{y}
  Define a subclass of this class, named x, with inner definitions y.

x y z
  Define a function as the class method; the syntax is same as that of a
  global function definition. You can make a new definition in a subclass
  but the definition in the subclass must have the same type.

x=:y
  Define the type of a class constant x as type y. Subclasses inherit this
  class constant with the same type.

x=y
  Define the value of a class constant (must be a compile time constant
  expression). Subclasses inherit this value by default but can redefine
  it with a different value (but must have the same type).

x:y
  Define the type of a property named x as type y. Subclasses will inherit
  all property types. No value is defined, though. After any property list
  expression involving this property is mentioned, it is then too late to
  add further properties to any of those classes. After the type, you may
  optionally add a quoted string, which is a "note".


=== Comments and preprocessor macros ===

Comments can be written by C style or C++ style (same as JavaScript).


=== Statements ===

=x
  Return value x (for a function that does not return, use = by itself
  with none afterward)

?x{y}
  If x then y

?x{y}|{z}
  If x then y else z

%x{y}
  While x do y

<x>y{z}
  For each element named x of y, do z (inside of the block z, x is a new
  variable whose type is the type of elements of y)

<<
  Continue

>>
  Break

x:y=z
  Declare variable named x of type y with initial value z

{x}
  Make a compound statement. Variables are scoped inside of it

;
  Do nothing (semicolons can be used to avoid ambiguity)


=== Expressions ===

A PLOCARF expression can be use the operators, but there is also the short
expressions which are one item, such as:

Numeric literal: Put a number which is decimal, or can be hexadecimal with
0x at front.

String literal: Make a pool string literal with quotation marks around it;
the syntax is otherwise JSON syntax of string literals.

List: Put [] with the items with commas in between.

Class name: Put # and the class name.

Null: Put . by itself for null object.

Variable or global function: You can use a name of a variable (including
arguments to the function) or a global function, to use its value.


=== Operators ===

x+y
  Addition, or list concatenation

x-y
  Subtraction; same as (x+(-y))

-y
  Negative (must be a number)

x*y
  Multiplication, or repeat list x, y times

x/y
  Integer division

x%y
  Remainder

!x
  Logical not (convert to boolean if applicable)

x$:t
  Type cast

x(y)
  Call function x, or access element y of list x; see the function call
  syntax section below

*x
  Class of object or length of list

~x
  Bitwise or boolean complement

x<<y
  Shift left

x>>y
  Shift y

x==y
  Compare if equal (usable with numbers, classes, objects, booleans, pool
  strings, and lists of any of these types)

x!=y
  Compare if unequal (usable with same types as equal)

x<y
  Compare if less (numbers only)

x>y
  Compare if greater (numbers only)

x<=y
  Compare if less or equal (numbers only)

x>=y
  Compare if greater or equal (numbers only)

x&&y
  Short-circuiting boolean and

x||y
  Short-circuiting boolean or

x&y
  Bitwise or boolean and

x|y
  Bitwise or boolean or

x^y
  Bitwise or boolean exclusive or

x=y
  Assignment (you can also use a combined assignment operator with any of
  + - * / % << >> & | ^ operators with = after (with no space))

x?y:z
  Conditional

x[y]
  Make property list

(x,y)
  Comma operator (the parentheses is require)

x.y
  Use property or method or constant name y of class x (if a constant, it
  is the value of the constant; otherwise it is the name)

x~y
  Map list y with function x


=== Function call syntax ===

The x(y) expression syntax can actually be use for many kind of things,
which are as follows (based on the type of x) (the y is zero or more
arguments with commas in between):

Function
  Call the function with the given arguments. The function has to be a
  (not necessarily strict) subset of permissions of the function that
  the call expression is in. If a function that does not return a value
  is expected, you can always still use a function that does return a
  value too, of any return type.

List
  Access the given list element (zero-based). In this case (only), you
  can have multiple arguments in case of nested lists (but this use of
  multi arguments is optional). If the number is out of range, it is an
  error (a JavaScript RangeError exception).

PropertyList
  With one argument (a property name), read the value of that property
  from the property list. Error if it is of the wrong class. With two
  arguments, the second is the new value, and the result is the new
  property list with that one property value changed.

MethodName
  It needs one argument, which is a class name. The result is the
  corresponding function from that class.

Class
  Needs one or more arguments. The first is a method name, and the rest
  are the arguments, and it calls it (subject to same restriction of
  permissions as above).

Object
  Similar to with a class, but the first argument to the function will
  be omitted because instead the object itself is passed.