M .hgignore +1 -0
@@ 28,6 28,7 @@ syntax: regexp
^testing/(_)?test\.wasm$
^scopes[.]h$
^doc/site
+^doc/site-packages
^bin/
^src/known_symbols.hpp
^Makefile$
M doc/Makefile +9 -3
@@ 2,9 2,9 @@
#
# You can set these variables from the command line.
-MKDOCSOPTS =
MKDOCS = mkdocs
BUILDDIR = site
+PYBUILDDIR = site-packages
# User-friendly check for MkDocs
ifeq ($(shell which $(MKDOCS) >/dev/null 2>&1; echo $$?), 1)
@@ 18,11 18,17 @@ help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " clean to discard generated documentation"
@echo " html to make standalone HTML files"
+ @echo " serve to start a web server in preview mode for editing"
clean:
- rm -rf $(BUILDDIR)/*
+ rm -rf $(BUILDDIR)/* $(PYBUILDDIR)/*
html:
- $(MKDOCS) $(MKDOCSOPTS) build -d $(BUILDDIR)
+ pip install --upgrade -I ./ScopesLexer -t $(PYBUILDDIR)
+ PYTHONPATH="$(PYBUILDDIR);$(PYTHONPATH)" python -B -m mkdocs build -d "$(BUILDDIR)"
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/."
+
+serve:
+ pip install --upgrade -I ./ScopesLexer -t $(PYBUILDDIR)
+ PYTHONPATH="$(PYBUILDDIR);$(PYTHONPATH)" python -B -m mkdocs serve
A => doc/ScopesLexer/scopeslexer/__init__.py +1 -0
M doc/scopeslexer.py => doc/ScopesLexer/scopeslexer/lexer.py +1 -1
@@ 113,7 113,7 @@ class ScopesLexer(Lexer):
return state.next_cursor - state.next_line + 1
def location_error(msg):
- print text
+ print(text)
raise Exception("%i:%i: error: %s" % (state.lineno,column(),msg))
def is_eof():
A => doc/ScopesLexer/setup.py +11 -0
@@ 0,0 1,11 @@
+from setuptools import setup, find_packages
+
+setup (
+ name='scopeslexer',
+ packages=find_packages(),
+ entry_points =
+ """
+ [pygments.lexers]
+ scopeslexer = scopeslexer.lexer:ScopesLexer
+ """,
+)
M doc/docs/cpp_users.md +350 -307
@@ 103,14 103,16 @@ only parses programs as symbolic lists a
declarations until the last possible moment, expecting all expressions to follow
just one basic form:
- # classic braced expression
- (head argument1 ... argumentN)
- # naked syntax
- head argument1 ... argumentN
- # naked paragraph form
- head argument1 ...
- ...
- argumentN
+```scopes
+# classic braced expression
+(head argument1 ... argumentN)
+# naked syntax
+head argument1 ... argumentN
+# naked paragraph form
+head argument1 ...
+ ...
+ argumentN
+```
The value and type of the head controls whether the expression is dispatched to:
@@ 199,22 201,24 @@ Scopes does not make such a distinction,
as an expression with a result type. The top level of a program is equivalent
to its main function:
- # the right hand side is not limited to constant expressions.
- let MyInt = int
+```scopes
+# the right hand side is not limited to constant expressions.
+let MyInt = int
- # legal at this level.
- print "hello!"
+# legal at this level.
+print "hello!"
- fn test (x)
- let k = (x * x)
+fn test (x)
+ let k = (x * x)
- let m =
- do
- # equivalent to statement expressions in GCC.
- print "hello again!"
- k * k
- # even `return` declares an expression of type `noreturn`.
- return m
+ let m =
+ do
+ # equivalent to statement expressions in GCC.
+ print "hello again!"
+ k * k
+ # even `return` declares an expression of type `noreturn`.
+ return m
+```
Constants and Variables
-----------------------
@@ 253,42 257,46 @@ expression or value to a name. The type
depends entirely on the expression that produces it. The `local` and `global`
forms must be used to explicitly allocate a stack or data segment value:
- # a compile time constant integer
- let constant = 100
+```scopes
+# a compile time constant integer
+let constant = 100
- # not a global value, but allocated on the main function's stack
- local variable1 = 0
- # a global value mapped to data segment
- global variable2 = 0
+# not a global value, but allocated on the main function's stack
+local variable1 = 0
+# a global value mapped to data segment
+global variable2 = 0
- # variable1 is bound to another name - not a copy operation.
- variable1_copy remains mutable.
- let variable1_copy = variable1
+# variable1 is bound to another name - not a copy operation.
+ variable1_copy remains mutable.
+let variable1_copy = variable1
- fn test ()
- # just a rebind - not a copy operation
- let variable3 = constant
- # variable3 is not a reference, so can not be mutated.
- we should have declared it as local for that.
- # variable3 = variable2
+fn test ()
+ # just a rebind - not a copy operation
+ let variable3 = constant
+ # variable3 is not a reference, so can not be mutated.
+ we should have declared it as local for that.
+ # variable3 = variable2
- print constant
- # illegal: variable1 is a stack variable outside of function scope
- # print variable1
- # legal: variable2 is a global
- print variable2
- # variable3 is a constant
- print variable3
+ print constant
+ # illegal: variable1 is a stack variable outside of function scope
+ # print variable1
+ # legal: variable2 is a global
+ print variable2
+ # variable3 is a constant
+ print variable3
+```
Unlike in C/C++, declarations of the same name within the same scope are
permitted, and the previous binding is still accessible during evaluation
of the right-hand side:
- let x = 1
- # x is now bound to the value 3
- let x = (x + 2)
- # x is now bound to a string
- let x = "test"
+```scopes
+let x = 1
+# x is now bound to the value 3
+let x = (x + 2)
+# x is now bound to a string
+let x = "test"
+```
Lexical Scope
-------------
@@ 298,18 306,20 @@ Both C/C++ and Scopes employ lexical sco
Unlike in C/C++, lexical scope is a first order object in Scopes and can be used
by new declarative forms as well as to export symbols from modules:
- let scope =
- do
- let x = 1
- let y = "test"
+```scopes
+let scope =
+ do
+ let x = 1
+ let y = "test"
- # build a new scope from locally bound names
- locals;
+ # build a new scope from locally bound names
+ locals;
- # scope is constant if all values in it are constant
- static-assert (constant? scope)
- # prints 1 "test"
- print scope.x scope.y
+# scope is constant if all values in it are constant
+static-assert (constant? scope)
+# prints 1 "test"
+print scope.x scope.y
+```
Macros
------
@@ 384,39 394,41 @@ In Scopes, all function declarations are
be used to instantiate concrete functions at compile time. Forward declarations
are possible but must be completed within the same scope:
- # forward declarations can not be typed
- #fn typed_forward_decl
-
- fn typed_decl (x text toggle)
- return 0
+```scopes
+# forward declarations can not be typed
+#fn typed_forward_decl
- # create typed function
- let typed_decl = (static-typify typed_decl i32 rawstring bool)
+fn typed_decl (x text toggle)
+ return 0
- # forward declaration of template has no parameter list
- fn lazy_typed_decl_returns_void
+# create typed function
+let typed_decl = (static-typify typed_decl i32 rawstring bool)
+
+# forward declaration of template has no parameter list
+fn lazy_typed_decl_returns_void
- # test1 is another template
- fn test1 ()
- # legal because test1 is not instantiated yet
- # note: lazy_typed_decl_returns_void must be implemented before
- test1 is instantiated.
- lazy_typed_decl_returns_void 1 2 3
+# test1 is another template
+fn test1 ()
+ # legal because test1 is not instantiated yet
+ # note: lazy_typed_decl_returns_void must be implemented before
+ test1 is instantiated.
+ lazy_typed_decl_returns_void 1 2 3
- # forward declaration of template with auto return type
- note that all our forward declarations have no return type
- fn lazy_typed_decl_returns_auto
+# forward declaration of template with auto return type
+ note that all our forward declarations have no return type
+fn lazy_typed_decl_returns_auto
- fn test2 ()
- # legal because test2 is not instantiated yet
- lazy_typed_decl_returns_auto 1 2 3
+fn test2 ()
+ # legal because test2 is not instantiated yet
+ lazy_typed_decl_returns_auto 1 2 3
- # implementation of template with auto return type
- fn lazy_typed_decl_returns_auto (a b c)
- return 0
+# implementation of template with auto return type
+fn lazy_typed_decl_returns_auto (a b c)
+ return 0
- # instantiate test2
- let test2 = (static-typify test2)
+# instantiate test2
+let test2 = (static-typify test2)
+```
Variadic Arguments
------------------
@@ 431,29 443,31 @@ Functions in Scopes do not support runti
variadic C functions is supported), but support compile time variadic arguments.
See the following example:
- # any trailing parameter ending in '...' is interpreted to be variadic.
- fn takes-varargs (x y rest...)
- # count the number of arguments in rest...
- let numargs = (va-countof rest...)
+```scopes
+# any trailing parameter ending in '...' is interpreted to be variadic.
+fn takes-varargs (x y rest...)
+ # count the number of arguments in rest...
+ let numargs = (va-countof rest...)
- # use let's support for variadic values to split arguments into
- first argument and remainder.
- let z rest... = rest...
+ # use let's support for variadic values to split arguments into
+ first argument and remainder.
+ let z rest... = rest...
- # get the 5th argument from rest...
- let fifth_arg = (va@ 5 rest...)
+ # get the 5th argument from rest...
+ let fifth_arg = (va@ 5 rest...)
- # iterate through all arguments, perform an action on each one
- and store the result in a new variadic value.
- let processed... =
- va-map
- inline (value)
- print value
- value + 1
- rest...
+ # iterate through all arguments, perform an action on each one
+ and store the result in a new variadic value.
+ let processed... =
+ va-map
+ inline (value)
+ print value
+ value + 1
+ rest...
- # return variadic result as multiple return values
- return processed...
+ # return variadic result as multiple return values
+ return processed...
+```
Overloading
-----------
@@ 475,21 489,23 @@ Scopes offers a similar mechanism as a l
overloads are grouped at the time of declaration. The first form that
matches argument types implicitly is selected, in order of declaration:
- fn... overloaded
- case (a : i32, b : i32)
- return 0
- case (a : i32, b : f32)
- return 1
- case (a : f32, b : i32)
- return 2
+```scopes
+fn... overloaded
+case (a : i32, b : i32)
+ return 0
+case (a : i32, b : f32)
+ return 1
+case (a : f32, b : i32)
+ return 2
- # expanding overloaded in a different file, limited to local scope
+# expanding overloaded in a different file, limited to local scope
- # overwrites the previous declaration
- fn... overloaded
- case using overloaded # chains the previous declaration
- case (a : f32, b : f32) # will be tried last
- return 3
+# overwrites the previous declaration
+fn... overloaded
+case using overloaded # chains the previous declaration
+case (a : f32, b : f32) # will be tried last
+ return 3
+```
Code Generation
---------------
@@ 538,39 554,43 @@ libraries' or module's functions are act
Scopes also supports embedding existing third party C libraries in the classical
way, using `include`, `load-library` and `load-object`:
- # how to create trivial bindings for a C library
+```scopes
+# how to create trivial bindings for a C library
- # include thirdparty.h and make its declarations available as a scope object
- let thirdparty =
- include "thirdparty.h"
- options "-I" (module-dir .. "/../include") # specify options for clang
+# include thirdparty.h and make its declarations available as a scope object
+let thirdparty =
+ include "thirdparty.h"
+ options "-I" (module-dir .. "/../include") # specify options for clang
- # access a define from thirdparty.h
- if thirdparty.define.USE_SHARED_LIBRARY
- # load thirdparty as a shared library from system search paths
- if (operating-system == 'windows)
- load-library "thirdparty.dll"
- else
- load-library "libthirdparty.so"
+# access a define from thirdparty.h
+if thirdparty.define.USE_SHARED_LIBRARY
+ # load thirdparty as a shared library from system search paths
+ if (operating-system == 'windows)
+ load-library "thirdparty.dll"
else
- # load thirdparty as a static library from an object file
- load-object (module-dir .. "/../lib/thirdparty.o")
+ load-library "libthirdparty.so"
+else
+ # load thirdparty as a static library from an object file
+ load-object (module-dir .. "/../lib/thirdparty.o")
- # assemble a ready-to-use scope object for this module
- do
- # import only symbols beginning with thirdparty
- using thirdparty.define filter "^THIRDPARTY_.*$"
- using thirdparty.typedef filter "^thirdparty_.*$"
- using thirdparty.const filter "^thirdparty_.*$"
- using thirdparty.extern filter "^thirdparty_.*$"
+# assemble a ready-to-use scope object for this module
+do
+ # import only symbols beginning with thirdparty
+ using thirdparty.define filter "^THIRDPARTY_.*$"
+ using thirdparty.typedef filter "^thirdparty_.*$"
+ using thirdparty.const filter "^thirdparty_.*$"
+ using thirdparty.extern filter "^thirdparty_.*$"
- locals;
+ locals;
+```
Externals using C signatures can also be defined and used directly:
- let puts = (extern 'puts (function i32 rawstring))
- # definition becomes immediately available
- puts "hello\n"
+```scopes
+let puts = (extern 'puts (function i32 rawstring))
+# definition becomes immediately available
+puts "hello\n"
+```
Type Primitives
---------------
@@ 639,17 659,19 @@ Example example = { .value = 100, .text
to this equivalent declaration in Scopes:
- using import struct
+```scopes
+using import struct
- struct Example plain
- value : i32
- # type can be deduced from initializer
- choice = false
- text : rawstring = ""
+struct Example plain
+ value : i32
+ # type can be deduced from initializer
+ choice = false
+ text : rawstring = ""
- global example : Example
- value = 100
- text = "test"
+global example : Example
+ value = 100
+ text = "test"
+```
Methods
-------
@@ 683,18 705,20 @@ void use_example (Example example) {
Scopes supports methods in a more explicit way that makes refactorings from
function to method and back easier, both in declaration and in usage:
- struct Example plain
- value : i32
+```scopes
+struct Example plain
+ value : i32
- # note the explicit presence of the object parameter
- fn get_add_value (self n)
- self.value + n
+ # note the explicit presence of the object parameter
+ fn get_add_value (self n)
+ self.value + n
- fn print_value_plus_one (self)
- print ('get_add_value self 1)
+ fn print_value_plus_one (self)
+ print ('get_add_value self 1)
- fn use_example (example)
- 'print_value_plus_one example
+fn use_example (example)
+ 'print_value_plus_one example
+```
What happens here is that we call a quoted symbol with arguments. The call
handler for the `Symbol` type rewrites `'methodname object arg0 ... argN`
@@ 715,26 739,28 @@ Access modifiers are not available, but
their definition local. Fields can not be hidden, but they can be visibly
marked as private by convention:
- struct Example plain
- # an underscore indicates that the attribute is not meant to be
- accessed directly.
- _value : i32
+```scopes
+struct Example plain
+ # an underscore indicates that the attribute is not meant to be
+ accessed directly.
+ _value : i32
- fn get_add_value (self n)
- self._value + n
+ fn get_add_value (self n)
+ self._value + n
- fn print_value_plus_one (self)
- # use get_add_value directly
- print (get_add_value self 1)
+ fn print_value_plus_one (self)
+ # use get_add_value directly
+ print (get_add_value self 1)
- # unbind get_add_value from local scope to prevent it
- from being added as an attribute to Example.
- unlet get_add_value
+ # unbind get_add_value from local scope to prevent it
+ from being added as an attribute to Example.
+ unlet get_add_value
- fn use_example (example)
- # this operation is not possible from here:
- # 'get_add_value example 1
- 'print_value_plus_one example
+fn use_example (example)
+ # this operation is not possible from here:
+ # 'get_add_value example 1
+ 'print_value_plus_one example
+```
Template Classes
----------------
@@ 756,16 782,18 @@ struct Example {
Scopes leverages constant expression folding and compile time closures to
trivially provide this feature via `inline` functions:
- # a function decorator memoizes the result so we get the same type for
- the same arguments
- @@ memo
- inline Example (T x)
- # construct type name from string
- struct ("Example<" .. (tostring T) .. ">")
- value : T
+```scopes
+# a function decorator memoizes the result so we get the same type for
+ the same arguments
+@@ memo
+inline Example (T x)
+ # construct type name from string
+ struct ("Example<" .. (tostring T) .. ">")
+ value : T
- fn compare ()
- value == x
+ fn compare ()
+ value == x
+```
Partial template specialization allows the choice of different implementations
depending on instantiation arguments. The same mechanism is also used to do
@@ 796,29 824,31 @@ In Scopes, it is not necessary to create
type based dispatch operators. Here are three ways to supply the same
functionality:
- include "stdlib.h"
+```scopes
+include "stdlib.h"
- # a function that generates a function
- @@ memo
- inline to_int1 (T)
- static-match T
- case i32 _
- case rawstring atoi
- default
- static-error "unsupported type"
+# a function that generates a function
+@@ memo
+inline to_int1 (T)
+ static-match T
+ case i32 _
+ case rawstring atoi
+ default
+ static-error "unsupported type"
- # a function that performs the operation directly
- inline to_int2 (x)
- let T = (typeof x)
- static-if (T == i32) x
- elseif (T == rawstring) (atoi x)
- else
- static-error "unsupported type"
+# a function that performs the operation directly
+inline to_int2 (x)
+ let T = (typeof x)
+ static-if (T == i32) x
+ elseif (T == rawstring) (atoi x)
+ else
+ static-error "unsupported type"
- # using the overloaded function abstraction
- fn... to_int3
- case (x : i32,) x
- case (x : rawstring,) (atoi x)
+# using the overloaded function abstraction
+fn... to_int3
+case (x : i32,) x
+case (x : rawstring,) (atoi x)
+```
Constructors
------------
@@ 830,15 860,17 @@ first argument is the name of the type t
Here is an example that changes the default constructor of a struct:
- struct Example plain
- _value : i32
+```scopes
+struct Example plain
+ _value : i32
- inline __typecall (cls n)
- # within the context of a struct definition, super-type is bound
- to the super type of the struct we are defining. In this case
- the supertype is `CStruct`.
- super-type.__typecall cls
- _value = (n * n)
+ inline __typecall (cls n)
+ # within the context of a struct definition, super-type is bound
+ to the super type of the struct we are defining. In this case
+ the supertype is `CStruct`.
+ super-type.__typecall cls
+ _value = (n * n)
+```
Destructors
-----------
@@ 870,19 902,20 @@ referenced only at a single point within
a unique type is able to supply a destructor through the `__drop` special method
that is automatically called when the value goes out of scope:
- struct Handle
- _handle : voidstar
-
- # constructor
- inline __typecall (cls handle)
- super-type.__typecall cls handle
+```scopes
+struct Handle
+ _handle : voidstar
- # destructor
- inline __drop (self)
- print "destroying handle"
- free self._handle
- return;
+ # constructor
+ inline __typecall (cls handle)
+ super-type.__typecall cls handle
+ # destructor
+ inline __drop (self)
+ print "destroying handle"
+ free self._handle
+ return;
+```
Operator Overloading
--------------------
@@ 918,31 951,33 @@ protocols that any type can support by e
special attributes. See this equivalent example, which applies not only to
structs, but any type definition:
- struct Accumulable
- # one compile time function for all left-hand side variants receives
- left-hand and right-hand types and returns a function which can
- perform the operation or void.
- inline __+ (cls T)
- # test for type + type
- static-if (T == this-type)
- # return new closure
- inline (self other)
- this-type (self.value + other.value)
- # if T can be implicitly cast to i32, support it
- elseif (imply? T i32)
- inline (self other)
- this-type (self.value + other)
+```scopes
+struct Accumulable
+ # one compile time function for all left-hand side variants receives
+ left-hand and right-hand types and returns a function which can
+ perform the operation or void.
+ inline __+ (cls T)
+ # test for type + type
+ static-if (T == this-type)
+ # return new closure
+ inline (self other)
+ this-type (self.value + other.value)
+ # if T can be implicitly cast to i32, support it
+ elseif (imply? T i32)
+ inline (self other)
+ this-type (self.value + other)
- # another function covers all right-hand side variants
- inline __r+ (T cls)
- static-if (imply? T i32)
- inline (self other)
- this-type (self + other.value)
+ # another function covers all right-hand side variants
+ inline __r+ (T cls)
+ static-if (imply? T i32)
+ inline (self other)
+ this-type (self + other.value)
- value : i32
+ value : i32
- inline __repr (self)
- tostring self.value
+ inline __repr (self)
+ tostring self.value
+```
Standard Library
----------------
@@ 1032,20 1067,22 @@ Scopes supports compile time closures na
runtime closures are also supported through so-called captures. The example
above would be translated as follows:
- fn print_bound_constant ()
- let y = 42
- # capture constant `y` along with the function
- fn f (x)
- x + y
- # prints 65
- print (f 23)
+```scopes
+fn print_bound_constant ()
+ let y = 42
+ # capture constant `y` along with the function
+ fn f (x)
+ x + y
+ # prints 65
+ print (f 23)
- fn print_bound_value (y)
- # capture variable `y` along with the function
- capture f (x) {y}
- x + y
- # prints 65
- print (f 23)
+fn print_bound_value (y)
+ # capture variable `y` along with the function
+ capture f (x) {y}
+ x + y
+ # prints 65
+ print (f 23)
+```
Loops
-----
@@ 1083,28 1120,30 @@ Scopes defines a single builtin primitiv
backpropagation of immutable values, upon which various other library forms are
implemented:
- # implementing a counter using the range-based form
- for i in (range 10)
- print i
+```scopes
+# implementing a counter using the range-based form
+for i in (range 10)
+ print i
- # implementing an iterator using the loop primitive and immutable values
- loop (it k = (first container) 0)
- if (is_valid it)
- process k (at it)
- repeat (next it) (k + 1)
- else
- # break can return values
- break it k
+# implementing an iterator using the loop primitive and immutable values
+loop (it k = (first container) 0)
+ if (is_valid it)
+ process k (at it)
+ repeat (next it) (k + 1)
+ else
+ # break can return values
+ break it k
- # implementing a counter using a while loop and mutation
- local i = 0
- while (i < 10)
- print i
- i += 1
+# implementing a counter using a while loop and mutation
+local i = 0
+while (i < 10)
+ print i
+ i += 1
- # range-based form implementing an iterator
- for key value in map
- process key value
+# range-based form implementing an iterator
+for key value in map
+ process key value
+```
In addition, with the `fold .. for .. in` form, Scopes combines both immutable
loop and range-based form.
@@ 1126,17 1165,19 @@ implement native GLSL types and function
See the following example implementing and compiling a pixel shader:
- using import glm
- using import glsl
+```scopes
+using import glm
+using import glsl
- in uv : vec2 (location = 0)
- out color : vec4 (location = 1)
- fn main ()
- color = (vec4 (uv * 0.5 + 0.5) 0 1)
+in uv : vec2 (location = 0)
+out color : vec4 (location = 1)
+fn main ()
+ color = (vec4 (uv * 0.5 + 0.5) 0 1)
- print
- compile-glsl 330 'fragment
- static-typify main
+print
+ compile-glsl 330 'fragment
+ static-typify main
+```
The program output is as follows:
@@ 1175,37 1216,39 @@ can be thrown as an exception using the
the `try .. catch` form.
```c++
- struct myexception {
- const char *what;
- };
+struct myexception {
+ const char *what;
+};
- void main () {
- try {
- // throw value of type myexception
- myexception exc = { "an error occurred" };
- throw exc;
- } catch (myexception& e) {
- // print content to screen
- std::cout << e.what << std::endl;
- }
+void main () {
+ try {
+ // throw value of type myexception
+ myexception exc = { "an error occurred" };
+ throw exc;
+ } catch (myexception& e) {
+ // print content to screen
+ std::cout << e.what << std::endl;
}
+}
```
Scopes supports a form of structured exception handling that is monomorphic,
light-weight and C compatible. A value of any type can be raised using the
`raise` form, and handled using the `try .. except` form:
- using import struct
+```scopes
+using import struct
- struct myexception
- what : string
+struct myexception
+ what : string
- try
- # raise value of type myexception
- raise (myexception "an error occurred")
- except (e)
- # print content to screen
- print e.what
+try
+ # raise value of type myexception
+ raise (myexception "an error occurred")
+except (e)
+ # print content to screen
+ print e.what
+```
The presence of an exception modifies the return type of a function to a hidden
tagged union type which returns which path the function returned on, and
M doc/docs/dataformat.md +298 -244
@@ 24,98 24,99 @@ At a Glance
As a summary, here is an example that provides an overview of all
the notation aspects:
- # below is some random data without any schema
+```scopes
+# below is some random data without any schema
- # a naked list of five 32-bit signed integers
- 1 2 3 4 5
+# a naked list of five 32-bit signed integers
+1 2 3 4 5
- # a list that begins with a symbol 'float-values:' and contains a braced
- # sublist of floats.
- float-values: (1.0 2.0 3.1 4.2 5.5:f64 inf nan)
+# a list that begins with a symbol 'float-values:' and contains a braced
+# sublist of floats.
+float-values: (1.0 2.0 3.1 4.2 5.5:f64 inf nan)
- # we can also nest the sublist using indentation
- # note the extravagant heading, another context-free symbol.
- ==string-values==
- "A" "B" "NCC-1701\n" "\xFFD\xFF" "\"E\""
+# we can also nest the sublist using indentation
+# note the extravagant heading, another context-free symbol.
+==string-values==
+ "A" "B" "NCC-1701\n" "\xFFD\xFF" "\"E\""
- # a single top-level element, a single-line string
- "I am Locutus of Borg."
+# a single top-level element, a single-line string
+"I am Locutus of Borg."
- # a raw block string; four double quotes mark the start
- """"
- Ma'am is acceptable in a crunch, but I prefer Captain.
- -- Kathryn Janeway
+# a raw block string; four double quotes mark the start
+""""
+ Ma'am is acceptable in a crunch, but I prefer Captain.
+ -- Kathryn Janeway
- # a list of pairs (also lists), arranged horizontally
- (1 x) (2 y) (3 z)
- # same list, with last two entries arranged vertically
+# a list of pairs (also lists), arranged horizontally
+(1 x) (2 y) (3 z)
+# same list, with last two entries arranged vertically
+(1 x)
+ (2 y)
+ (3 z)
+# we can line up all entries by using a semicolon to indicate an empty head
+;
(1 x)
- (2 y)
- (3 z)
- # we can line up all entries by using a semicolon to indicate an empty head
- ;
- (1 x)
- (2 y)
- (3 z)
- # parentheses can also be removed for each line entry
- ;
- 1 x
- 2 y
- 3 z
+ (2 y)
+ (3 z)
+# parentheses can also be removed for each line entry
+;
+ 1 x
+ 2 y
+ 3 z
- # appending values to the parent list in the next line
- symbol-values one two three four five \
- six seven-of-nine ten
+# appending values to the parent list in the next line
+symbol-values one two three four five \
+ six seven-of-nine ten
- # line continuation can also begin at the start of the next line
- ::typed-integers:: 0:u8 1:i8 2:i16 3:u16
- \ 4:u32 5:i32 6:u64 7:i64
+# line continuation can also begin at the start of the next line
+::typed-integers:: 0:u8 1:i8 2:i16 3:u16
+ \ 4:u32 5:i32 6:u64 7:i64
- # which comes in handy when we want to continue the parent list
- people like
- jim kirk
- commander spock
- hikari sulu
- \ and many more
+# which comes in handy when we want to continue the parent list
+people like
+ jim kirk
+ commander spock
+ hikari sulu
+ \ and many more
- # a list with a symbol header and two entries
- address-list
- # a list with a header and three more lists of two values each
- entry
- name: "Jean-Luc Picard"
- age: 59
- address: picard@enterprise.org
- entry
- # the semicolon acts as list separator
- name: "Worf, Son of Mogh"; age: 24; address: worf@house-of-mogh.co.klingon
- # line comments double as block comments
- #entry
- name: "Natasha Yar"
- age: 27
- address: natasha.yar@enterprise.org
+# a list with a symbol header and two entries
+address-list
+ # a list with a header and three more lists of two values each
+ entry
+ name: "Jean-Luc Picard"
+ age: 59
+ address: picard@enterprise.org
+ entry
+ # the semicolon acts as list separator
+ name: "Worf, Son of Mogh"; age: 24; address: worf@house-of-mogh.co.klingon
+ # line comments double as block comments
+ #entry
+ name: "Natasha Yar"
+ age: 27
+ address: natasha.yar@enterprise.org
- # the same list with braced notation; within braced lists,
- indentation is meaningless.
- (address-list
- # a list with a header and three more lists of two values each
- (entry
- (name: "Jean-Luc Picard")
- (age: 59)
- (address: picard@enterprise.org))
- (entry (name: "Worf, Son of Mogh") (age: 24)
- (address: worf@house-of-mogh.co.klingon)))
+# the same list with braced notation; within braced lists,
+ indentation is meaningless.
+(address-list
+ # a list with a header and three more lists of two values each
+ (entry
+ (name: "Jean-Luc Picard")
+ (age: 59)
+ (address: picard@enterprise.org))
+ (entry (name: "Worf, Son of Mogh") (age: 24)
+ (address: worf@house-of-mogh.co.klingon)))
- # a list of comma separated values - a comma is always recorded as
- a separate symbol, so the list has nine entries
- 1, 2, 3,4, 5
+# a list of comma separated values - a comma is always recorded as
+ a separate symbol, so the list has nine entries
+1, 2, 3,4, 5
- # a list of options beginning with a symbol in a list with
- square brace style
- [task]
- cmd = "bash"
- # the last element is a symbol in a list with curly brace style
- working-dir = {project-base}
-
+# a list of options beginning with a symbol in a list with
+ square brace style
+[task]
+ cmd = "bash"
+ # the last element is a symbol in a list with curly brace style
+ working-dir = {project-base}
+```
Formatting Rules
@@ 147,14 148,16 @@ Both line and block comments are initiat
lasts from its beginning token to the first non-whitespace character with an equal
or lower indentation level. Some examples of valid comments:
- # a line comment
- not a comment
- # a block comment that continues
- in the next line because the line has
- a higher indentation level. Note, that
- comments do not need to respect
- indentation rules
- but this line is not a comment
+```scopes
+# a line comment
+not a comment
+# a block comment that continues
+ in the next line because the line has
+ a higher indentation level. Note, that
+ comments do not need to respect
+ indentation rules
+but this line is not a comment
+```
### Strings ###
@@ 168,8 171,10 @@ copied over verbatim.
Here are some examples of valid strings:
- "a single-line string in double quotations"
- "return: \n, tab: \t, backslash: \\, double quote: \", nbsp: \xFF."
+```scopes
+"a single-line string in double quotations"
+"return: \n, tab: \t, backslash: \\, double quote: \", nbsp: \xFF."
+```
### Raw Block Strings ###
@@ 180,13 185,15 @@ character that has a lower indentation.
Here are some examples of valid raw block strings:
- """"a single-line string as a block string
- # commented line inbetween
- """"// a multi-line string that describes a valid C function
- #include <stdio.h>
- void a_function_in_c() {
- printf("hello world\n");
- }
+```scopes
+""""a single-line string as a block string
+# commented line inbetween
+""""// a multi-line string that describes a valid C function
+ #include <stdio.h>
+ void a_function_in_c() {
+ printf("hello world\n");
+ }
+```
### Symbols ###
@@ 201,16 208,18 @@ As a special case, `,` is always parsed
Here are some examples of valid symbols:
- # classic underscore notation
- some_identifier _some_identifier
- # hyphenated
- some-identifier
- # mixed case
- SomeIdentifier
- # fantasy operators
- &+ >~ >>= and= str+str
- # numbered
- _42 =303
+```scopes
+# classic underscore notation
+some_identifier _some_identifier
+# hyphenated
+some-identifier
+# mixed case
+SomeIdentifier
+# fantasy operators
+&+ >~ >>= and= str+str
+# numbered
+_42 =303
+```
### Numbers ###
@@ 226,18 235,20 @@ to the number as well as a numerical typ
Here are some examples of valid numbers:
- # positive and negative integers in decimal and hexadecimal notation
- 0 +23 42 -303 12 -1 -0x20 0xAFFE
- # positive and negative reals
- 0.0 1.0 3.14159 -2.0 0.000003 0xa400.a400
- # reals in scientific notation
- 1.234e+24 -1e-12
- # special reals
- +inf -inf nan
- # zero as unsigned 64-bit integer and as signed 8-bit integer
- 0:u64 0:i8
- # a floating-point number with double precision
- 1.0:f64
+```scopes
+# positive and negative integers in decimal and hexadecimal notation
+0 +23 42 -303 12 -1 -0x20 0xAFFE
+# positive and negative reals
+0.0 1.0 3.14159 -2.0 0.000003 0xa400.a400
+# reals in scientific notation
+1.234e+24 -1e-12
+# special reals
++inf -inf nan
+# zero as unsigned 64-bit integer and as signed 8-bit integer
+0:u64 0:i8
+# a floating-point number with double precision
+1.0:f64
+```
### Lists ###
@@ 249,14 260,16 @@ only separated by whitespace. They typic
Here are some examples of valid lists:
- # a list of numbers in naked format
- 1 2 3 4 5
- # three empty braced lists within a naked list
- () () ()
- # a list containing a symbol, a string, an integer, a real, and an empty list
- (print (.. "hello world") 303 606 909)
- # three nesting lists
- ((()))
+```scopes
+# a list of numbers in naked format
+1 2 3 4 5
+# three empty braced lists within a naked list
+() () ()
+# a list containing a symbol, a string, an integer, a real, and an empty list
+(print (.. "hello world") 303 606 909)
+# three nesting lists
+((()))
+```
Naked & Braced Lists
--------------------
@@ 268,9 281,11 @@ to what [Lisp](http://en.wikipedia.org/w
[Scheme](http://en.wikipedia.org/wiki/Scheme_(programming_language)) authors
know as *restricted* [S-expressions](https://en.wikipedia.org/wiki/S-expression>):
- (print
- (.. "Hello" "World")
- 303 606 909)
+```scopes
+(print
+ (.. "Hello" "World")
+ 303 606 909)
+```
As a modern alternative, Scopes offers a *naked notation* where the scope of
lists is implicitly balanced by indentation, an approach used by
@@ 282,42 297,46 @@ other languages.
This source parses as the same list in the previous, braced example:
- # The same list as above, but in naked format.
- A sub-paragraph continues the list.
- print
- # elements on a single line with or without sub-paragraph are wrapped
- in a list.
- .. "Hello" "World"
+```scopes
+# The same list as above, but in naked format.
+ A sub-paragraph continues the list.
+print
+ # elements on a single line with or without sub-paragraph are wrapped
+ in a list.
+ .. "Hello" "World"
- # values that should not be wrapped have to be prefixed with an
- escape token which causes a continuation of the parent list
- \ 303 606 909
+ # values that should not be wrapped have to be prefixed with an
+ escape token which causes a continuation of the parent list
+ \ 303 606 909
+```
### Mixing Modes ###
Naked lists can contain braced lists, and braced lists can
contain naked lists:
- # compute the value of (1 + 2 + (3 * 4)) and print the result
- (print
- (+ 1 2
- (3 * 4)))
+```scopes
+# compute the value of (1 + 2 + (3 * 4)) and print the result
+(print
+ (+ 1 2
+ (3 * 4)))
- # the same list in naked notation.
- indented lists are appended to the parent list:
- print
- + 1 2
- 3 * 4
+# the same list in naked notation.
+ indented lists are appended to the parent list:
+print
+ + 1 2
+ 3 * 4
- # any part of a naked list can be braced
- print
- + 1 2 (3 * 4)
+# any part of a naked list can be braced
+print
+ + 1 2 (3 * 4)
- # and a braced list can contain naked parts.
- the escape character \ enters naked mode at its indentation level.
- print
- (+ 1 2
- \ 3 * 4) # parsed as (+ 1 2 (3 * 4))
+# and a braced list can contain naked parts.
+ the escape character \ enters naked mode at its indentation level.
+print
+ (+ 1 2
+ \ 3 * 4) # parsed as (+ 1 2 (3 * 4))
+```
Naked notation is strongly encouraged as it is more convenient for authors
without specialized editors to write and balancing parentheses can be
@@ 334,13 353,15 @@ square `[]` brace styles. They are merel
writing SLN-based formats, and are expanded to simple lists during parsing.
Some examples:
- [a b c d]
- # expands to
- (\[\] a b c d)
+```scopes
+[a b c d]
+# expands to
+(\[\] a b c d)
- {1 2 3 4}
- # expands to
- (\{\} 1 2 3 4)
+{1 2 3 4}
+# expands to
+(\{\} 1 2 3 4)
+```
List Separators
---------------
@@ 355,24 376,27 @@ mode by starting the head of the block w
Here are some examples:
- # in braced notation
- (print a; print (a;b;); print c;)
- # parses as
- ((print a) (print ((a) (b))) (print c))
+```scopes
+# in braced notation
+(print a; print (a;b;); print c;)
+# parses as
+((print a) (print ((a) (b))) (print c))
- # in naked notation
+# in naked notation
+;
+ print a; print b
;
- print a; print b
- ;
- print c; print d
- # parses as
- ((print a) (print b) ((print c) (print d)))
+ print c; print d
+# parses as
+((print a) (print b) ((print c) (print d)))
+```
!!! warning
If semicolons are used with braced notation then any trailing elements that
are not terminated with `;` will not be wrapped:
+ :::scopes
# in braced notation
(print a; print (a;b;); print c)
# parses as
@@ 392,27 416,37 @@ wants to wrap them in a list.
Here is a braced list describing an expression printing the number 42:
- (print 42)
+```scopes
+(print 42)
+```
The naked equivalent declares two elements in a single line, which are implicitly
wrapped in a single list:
- print 42
+```scopes
+print 42
+```
A single element on its own line is not wrapped:
- print # (print
- 42 # 42)
+```scopes
+print # (print
+ 42 # 42)
+```
What if we want to just print a newline, passing no arguments?:
- print # print
+```scopes
+print # print
+```
The statement above will be ignored because a symbol is resolved but not called.
One can make use of the `;` (split-statement) control
character, which ends the current list:
- print; # (print)
+```scopes
+print; # (print)
+```
### Continuation Lines ###
@@ 422,118 456,138 @@ column limit (typically 80 or 100).
In braced lists, the problem is easily corrected:
- # import many symbols from an external module into the active namespace
- (import-from "OpenGL"
- glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT
- GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram
- glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP)
+```scopes
+# import many symbols from an external module into the active namespace
+(import-from "OpenGL"
+ glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT
+ GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram
+ glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP)
+```
The naked approach interprets each new line as a nested list:
- # produces runtime errors
- import-from "OpenGL"
- glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT
- GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram
- glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP
+```scopes
+# produces runtime errors
+import-from "OpenGL"
+ glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT
+ GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram
+ glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP
- # braced equivalent of the term above; each line is interpreted
- # as a function call and fails.
- (import-from "OpenGL"
- (glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT)
- (GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram)
- (glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP))
+# braced equivalent of the term above; each line is interpreted
+# as a function call and fails.
+(import-from "OpenGL"
+ (glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT)
+ (GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram)
+ (glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP))
+```
This can be fixed by using the `splice-line` control character, `\`:
- # correct solution using splice-line, postfix-style
- import-from "OpenGL" \
- glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT \
- GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram \
- glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP
+```scopes
+# correct solution using splice-line, postfix-style
+import-from "OpenGL" \
+ glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT \
+ GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram \
+ glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP
+```
Unlike in other languages, and as previously demonstrated, `\` splices at the
token level rather than the character level, and can also be placed at the
beginning of nested lines, where the parent is still the active list:
- # correct solution using the splice-line control character '\', prefix-style
- import-from "OpenGL"
- \ glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT
- \ GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram
- \ glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP
+```scopes
+# correct solution using the splice-line control character '\', prefix-style
+import-from "OpenGL"
+ \ glBindBuffer GL_UNIFORM_BUFFER glClear GL_COLOR_BUFFER_BIT
+ \ GL_STENCIL_BUFFER_BIT GL_DEPTH_BUFFER_BIT glViewport glUseProgram
+ \ glDrawArrays glEnable glDisable GL_TRIANGLE_STRIP
+```
### Tail Splicing ###
Naked notation is ideal for writing nested lists that accumulate at the tail:
- # braced
- (a b c
- (d e f
- (g h i))
- (j k l))
+```scopes
+# braced
+(a b c
+ (d e f
+ (g h i))
+ (j k l))
- # naked
- a b c
- d e f
- g h i
- j k l
+# naked
+a b c
+ d e f
+ g h i
+ j k l
+```
However, there are complications when additional elements need to be spliced
back into the parent list:
- (a b c
- (d e f
- (g h i))
- j k l)
+```scopes
+(a b c
+ (d e f
+ (g h i))
+ j k l)
+```
Once again, we can reuse the splice-line control character `\` to get what we
want:
- a b c
- d e f
- g h i
- \ j k l
+```scopes
+a b c
+ d e f
+ g h i
+ \ j k l
+```
### Left-Hand Nesting ###
When using infix notation, conditional blocks, or functions producing functions,
lists occur that nest at the head level rather than the tail:
- ((((a b)
- c d)
- e f)
- g h)
+```scopes
+((((a b)
+ c d)
+ e f)
+ g h)
+```
The equivalent naked mode version makes extensive use of list separator and
splice-line characters to describe the same tree:
- # equivalent structure
+```scopes
+# equivalent structure
+;
;
;
- ;
- a b
- \ c d
- \ e f
- \ g h
+ a b
+ \ c d
+ \ e f
+ \ g h
+```
A more complex tree which also requires splicing elements back into the parent
list can be implemented with the same combination of list separator and
splice-line characters:
- # braced
- (a
- ((b
- (c d)) e)
- f g
- (h i))
+```scopes
+# braced
+(a
+ ((b
+ (c d)) e)
+ f g
+ (h i))
- # naked
- a
- ;
- b
- c d
- \ e
- \ f g
- h i
+# naked
+a
+ ;
+ b
+ c d
+ \ e
+ \ f g
+ h i
+```
While this example demonstrates the versatility of the splice-line and list
separator characters, use of partially braced notation may be easier to
M doc/docs/module-Array.md +57 -57
@@ 1,10 1,10 @@
<style type="text/css" rel="stylesheet">body { counter-reset: chapter 7; }</style>
-Array
-=====
-
-Provides mutable array types that store their elements on the heap rather
-than in registers or the stack.
+Array
+=====
+
+Provides mutable array types that store their elements on the heap rather
+than in registers or the stack.
*type*{.property} `Array`{.descname} [](#scopes.type.Array "Permalink to this definition"){.headerlink} {#scopes.type.Array}
@@ 12,69 12,69 @@ than in registers or the stack.
*fn*{.property} `__@`{.descname} (* self index *)[](#scopes.Array.fn.__@ "Permalink to this definition"){.headerlink} {#scopes.Array.fn.__@}
- : Implements support for the `@` operator. Returns a view reference to the
- element at `index` of array `self`.
+ : Implements support for the `@` operator. Returns a view reference to the
+ element at `index` of array `self`.
*inline*{.property} `__as`{.descname} (* cls T *)[](#scopes.Array.inline.__as "Permalink to this definition"){.headerlink} {#scopes.Array.inline.__as}
- : Implements support for the `as` operator. Arrays can be cast to
- `Generator`, or directly passed to `for`.
+ : Implements support for the `as` operator. Arrays can be cast to
+ `Generator`, or directly passed to `for`.
*inline*{.property} `__countof`{.descname} (* self *)[](#scopes.Array.inline.__countof "Permalink to this definition"){.headerlink} {#scopes.Array.inline.__countof}
- : Implements support for the `countof` operator. Returns the current
- number of elements stored in `self` as a value of `usize` type.
+ : Implements support for the `countof` operator. Returns the current
+ number of elements stored in `self` as a value of `usize` type.
*inline*{.property} `__drop`{.descname} (* self *)[](#scopes.Array.inline.__drop "Permalink to this definition"){.headerlink} {#scopes.Array.inline.__drop}
- : Implements support for freeing the array's memory when it goes out
- of scope.
+ : Implements support for freeing the array's memory when it goes out
+ of scope.
*inline*{.property} `__imply`{.descname} (* cls T *)[](#scopes.Array.inline.__imply "Permalink to this definition"){.headerlink} {#scopes.Array.inline.__imply}
- : Implements support for pointer casts, to pass the array to C functions
- for example.
+ : Implements support for pointer casts, to pass the array to C functions
+ for example.
*inline*{.property} `__typecall`{.descname} (* cls element-type capacity *)[](#scopes.Array.inline.__typecall "Permalink to this definition"){.headerlink} {#scopes.Array.inline.__typecall}
- : Construct a mutable array type of `element-type` with a variable or
- fixed maximum capacity.
-
- If `capacity` is defined, then it specifies the maximum number
- of array elements permitted. If it is undefined, then an initial
- capacity of 16 elements is assumed, which is doubled whenever
- it is exceeded, allowing for an indefinite number of elements.
+ : Construct a mutable array type of `element-type` with a variable or
+ fixed maximum capacity.
+
+ If `capacity` is defined, then it specifies the maximum number
+ of array elements permitted. If it is undefined, then an initial
+ capacity of 16 elements is assumed, which is doubled whenever
+ it is exceeded, allowing for an indefinite number of elements.
*fn*{.property} `append`{.descname} (* self value *)[](#scopes.Array.fn.append "Permalink to this definition"){.headerlink} {#scopes.Array.fn.append}
- : Append `value` as an element to the array `self` and return a reference
- to the new element. When the `array` is of `GrowingArray` type, this
- operation will transparently resize the array's storage.
+ : Append `value` as an element to the array `self` and return a reference
+ to the new element. When the `array` is of `GrowingArray` type, this
+ operation will transparently resize the array's storage.
*fn*{.property} `clear`{.descname} (* self *)[](#scopes.Array.fn.clear "Permalink to this definition"){.headerlink} {#scopes.Array.fn.clear}
- : Clear the array and reset its element count to zero. This will drop
- all elements that have been previously contained by the array.
+ : Clear the array and reset its element count to zero. This will drop
+ all elements that have been previously contained by the array.
*inline*{.property} `emplace-append`{.descname} (* self args... *)[](#scopes.Array.inline.emplace-append "Permalink to this definition"){.headerlink} {#scopes.Array.inline.emplace-append}
- : Construct a new element with arguments `args...` directly in a newly
- assigned slot of array `self`. When the `array` is of `GrowingArray`
- type, this operation will transparently resize the array's storage.
+ : Construct a new element with arguments `args...` directly in a newly
+ assigned slot of array `self`. When the `array` is of `GrowingArray`
+ type, this operation will transparently resize the array's storage.
*inline*{.property} `emplace-append-many`{.descname} (* self size args... *)[](#scopes.Array.inline.emplace-append-many "Permalink to this definition"){.headerlink} {#scopes.Array.inline.emplace-append-many}
- : Construct a new element with arguments `args...` directly in a newly
- assigned slot of array `self`. When the `array` is of `GrowingArray`
- type, this operation will transparently resize the array's storage.
+ : Construct a new element with arguments `args...` directly in a newly
+ assigned slot of array `self`. When the `array` is of `GrowingArray`
+ type, this operation will transparently resize the array's storage.
*type*{.property} `insert`{.descname} [](#scopes.Array.type.insert "Permalink to this definition"){.headerlink} {#scopes.Array.type.insert}
- : Insert `value` at `index` into the array `self` and return a reference
- to the new element. When the `array` is of `GrowingArray` type, this
- operation will transparently resize the array's storage.
- This operation offsets the index of each following element by 1.
- If index is omitted, `insert` operates like `append`.
+ : Insert `value` at `index` into the array `self` and return a reference
+ to the new element. When the `array` is of `GrowingArray` type, this
+ operation will transparently resize the array's storage.
+ This operation offsets the index of each following element by 1.
+ If index is omitted, `insert` operates like `append`.
*fn*{.property} `last`{.descname} (* self *)[](#scopes.Array.fn.last "Permalink to this definition"){.headerlink} {#scopes.Array.fn.last}
@@ 82,17 82,17 @@ than in registers or the stack.
*fn*{.property} `pop`{.descname} (* self *)[](#scopes.Array.fn.pop "Permalink to this definition"){.headerlink} {#scopes.Array.fn.pop}
- : Remove element with highest index from array `self` and return it.
+ : Remove element with highest index from array `self` and return it.
*fn*{.property} `remove`{.descname} (* self index *)[](#scopes.Array.fn.remove "Permalink to this definition"){.headerlink} {#scopes.Array.fn.remove}
- : Remove element at index from array `self` and return it.
- This operation offsets the index of each following element by -1.
+ : Remove element at index from array `self` and return it.
+ This operation offsets the index of each following element by -1.
*fn*{.property} `resize`{.descname} (* self count args... *)[](#scopes.Array.fn.resize "Permalink to this definition"){.headerlink} {#scopes.Array.fn.resize}
- : Resize the array to the specified count. Items are apppend or removed
- to meet the desired count.
+ : Resize the array to the specified count. Items are apppend or removed
+ to meet the desired count.
*inline*{.property} `reverse`{.descname} (* self *)[](#scopes.Array.inline.reverse "Permalink to this definition"){.headerlink} {#scopes.Array.inline.reverse}
@@ 100,14 100,14 @@ than in registers or the stack.
*inline*{.property} `sort`{.descname} (* self key ... *)[](#scopes.Array.inline.sort "Permalink to this definition"){.headerlink} {#scopes.Array.inline.sort}
- : Sort elements of array `self` from smallest to largest, either using
- the `<` operator supplied by the element type, or by using the key
- supplied by the callable `key`, which is expected to return a comparable
- value for each element value supplied.
+ : Sort elements of array `self` from smallest to largest, either using
+ the `<` operator supplied by the element type, or by using the key
+ supplied by the callable `key`, which is expected to return a comparable
+ value for each element value supplied.
*fn*{.property} `swap`{.descname} (* self a b *)[](#scopes.Array.fn.swap "Permalink to this definition"){.headerlink} {#scopes.Array.fn.swap}
- : Safely swap the contents of two indices.
+ : Safely swap the contents of two indices.
*type*{.property} `FixedArray`{.descname} [](#scopes.type.FixedArray "Permalink to this definition"){.headerlink} {#scopes.type.FixedArray}
@@ 115,7 115,7 @@ than in registers or the stack.
*fn*{.property} `__repr`{.descname} (* self *)[](#scopes.FixedArray.fn.__repr "Permalink to this definition"){.headerlink} {#scopes.FixedArray.fn.__repr}
- : Implements support for the `repr` operation.
+ : Implements support for the `repr` operation.
*inline*{.property} `__typecall`{.descname} (* cls opts... *)[](#scopes.FixedArray.inline.__typecall "Permalink to this definition"){.headerlink} {#scopes.FixedArray.inline.__typecall}
@@ 123,13 123,13 @@ than in registers or the stack.
*inline*{.property} `capacity`{.descname} (* self *)[](#scopes.FixedArray.inline.capacity "Permalink to this definition"){.headerlink} {#scopes.FixedArray.inline.capacity}
- : Returns the maximum capacity of array `self`, which is fixed.
+ : Returns the maximum capacity of array `self`, which is fixed.
*fn*{.property} `reserve`{.descname} (* self count *)[](#scopes.FixedArray.fn.reserve "Permalink to this definition"){.headerlink} {#scopes.FixedArray.fn.reserve}
- : Internally used by the type. Ensures that array `self` can hold at least
- `count` elements. A fixed array will raise an assertion when its
- capacity has been exceeded.
+ : Internally used by the type. Ensures that array `self` can hold at least
+ `count` elements. A fixed array will raise an assertion when its
+ capacity has been exceeded.
*type*{.property} `GrowingArray`{.descname} [](#scopes.type.GrowingArray "Permalink to this definition"){.headerlink} {#scopes.type.GrowingArray}
@@ 137,7 137,7 @@ than in registers or the stack.
*fn*{.property} `__repr`{.descname} (* self *)[](#scopes.GrowingArray.fn.__repr "Permalink to this definition"){.headerlink} {#scopes.GrowingArray.fn.__repr}
- : Implements support for the `repr` operation.
+ : Implements support for the `repr` operation.
*inline*{.property} `__typecall`{.descname} (* cls opts... *)[](#scopes.GrowingArray.inline.__typecall "Permalink to this definition"){.headerlink} {#scopes.GrowingArray.inline.__typecall}
@@ 145,10 145,10 @@ than in registers or the stack.
*inline*{.property} `capacity`{.descname} (* self *)[](#scopes.GrowingArray.inline.capacity "Permalink to this definition"){.headerlink} {#scopes.GrowingArray.inline.capacity}
- : Returns the current maximum capacity of array `self`.
+ : Returns the current maximum capacity of array `self`.
*fn*{.property} `reserve`{.descname} (* self count *)[](#scopes.GrowingArray.fn.reserve "Permalink to this definition"){.headerlink} {#scopes.GrowingArray.fn.reserve}
- : Internally used by the type. Ensures that array `self` can hold at least
- `count` elements. A growing array will always attempt to comply.
+ : Internally used by the type. Ensures that array `self` can hold at least
+ `count` elements. A growing array will always attempt to comply.
M doc/docs/module-FunctionChain.md +2 -0
@@ 8,6 8,7 @@ a module to call back into dependent mod
See following example:
+ :::scopes
using import FunctionChain
# declare new function chain
@@ 34,6 35,7 @@ See following example:
Running this program will output:
+ :::text
first handler activated with argument 1
handler activated with argument 1
last handler activated with argument 1
M doc/docs/module-core.md +7 -0
@@ 888,6 888,7 @@ parses the command-line and optionally e
Here is a typical pattern for constructing a generator:
+ :::scopes
inline make-generator (container)
Generator
inline "start" ()
@@ 905,6 906,7 @@ parses the command-line and optionally e
The generator can then be subsequently used like this:
+ :::scopes
# this example prints up to two elements returned by a generator
# generate a new instance bound to container
let gen = (make-generator container)
@@ 2762,12 2764,14 @@ parses the command-line and optionally e
: usage example:
+ :::scopes
error@ ('anchor value) "while checking parameter" "error in value"
*fn*{.property} `error@+`{.descname} (* error anchor traceback-msg *)[](#scopes.fn.error@+ "Permalink to this definition"){.headerlink} {#scopes.fn.error@+}
: usage example:
+ :::scopes
except (err)
error@+ err ('anchor value) "while processing stream"
@@ 3279,6 3283,7 @@ parses the command-line and optionally e
: uncomma list l, wrapping all comma separated symbols as new lists
example:
+ :::scopes
(uncomma '(a , b c d , e f , g h)) -> '(a (b c d) (e f) (g h))
*fn*{.property} `unpack-infix-op`{.descname} (* op *)[](#scopes.fn.unpack-infix-op "Permalink to this definition"){.headerlink} {#scopes.fn.unpack-infix-op}
@@ 3425,6 3430,7 @@ parses the command-line and optionally e
Usage example:
+ :::scopes
# add numbers from 0 to 9, skipping number 5, and print the result
print
fold (sum = 0) for i in (range 100)
@@ 4641,6 4647,7 @@ parses the command-line and optionally e
: This function can be used in conjunction with `from`:
+ :::scopes
from (methodsof <object>) let method1 method2
now the imported methods are implicitly bound to `<object>` and can be
M doc/docs/module-testing.md +2 -0
@@ 77,6 77,7 @@ fashion.
usage:
+ :::scopes
features B1 B2 B3 ...
---
A1 Y N Y
@@ 85,6 86,7 @@ fashion.
will expand to:
+ :::scopes
do
Y A1 B1; N A1 B2; Y A1 B3
N A2 B1; Y A2 B2; N A2 B3
A => doc/docs/pygments.css +69 -0
@@ 0,0 1,69 @@
+.codehilite .hll { background-color: #ffffcc }
+.codehilite { background: #f8f8f8; }
+.codehilite .c { color: #408080; font-style: italic } /* Comment */
+.codehilite .err { border: 1px solid #FF0000 } /* Error */
+.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
+.codehilite .o { color: #666666 } /* Operator */
+.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
+.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
+.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
+.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
+.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
+.codehilite .gd { color: #A00000 } /* Generic.Deleted */
+.codehilite .ge { font-style: italic } /* Generic.Emph */
+.codehilite .gr { color: #FF0000 } /* Generic.Error */
+.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.codehilite .gi { color: #00A000 } /* Generic.Inserted */
+.codehilite .go { color: #888888 } /* Generic.Output */
+.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.codehilite .gs { font-weight: bold } /* Generic.Strong */
+.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.codehilite .gt { color: #0044DD } /* Generic.Traceback */
+.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
+.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.codehilite .kt { color: #B00040 } /* Keyword.Type */
+.codehilite .m { color: #666666 } /* Literal.Number */
+.codehilite .s { color: #BA2121 } /* Literal.String */
+.codehilite .na { color: #7D9029 } /* Name.Attribute */
+.codehilite .nb { color: #008000 } /* Name.Builtin */
+.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.codehilite .no { color: #880000 } /* Name.Constant */
+.codehilite .nd { color: #AA22FF } /* Name.Decorator */
+.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
+.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+.codehilite .nf { color: #0000FF } /* Name.Function */
+.codehilite .nl { color: #A0A000 } /* Name.Label */
+.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
+.codehilite .nv { color: #19177C } /* Name.Variable */
+.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
+.codehilite .mb { color: #666666 } /* Literal.Number.Bin */
+.codehilite .mf { color: #666666 } /* Literal.Number.Float */
+.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
+.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
+.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
+.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
+.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
+.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
+.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
+.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
+.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
+.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+.codehilite .sx { color: #008000 } /* Literal.String.Other */
+.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
+.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
+.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
+.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
+.codehilite .fm { color: #0000FF } /* Name.Function.Magic */
+.codehilite .vc { color: #19177C } /* Name.Variable.Class */
+.codehilite .vg { color: #19177C } /* Name.Variable.Global */
+.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
+.codehilite .vm { color: #19177C } /* Name.Variable.Magic */
+.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
M doc/docs/tutorial.md +214 -162
@@ 18,24 18,30 @@ to start it is to simply launch the exec
is usually located in the root directory, and on Unix-compatible systems
it can simply be started from the terminal with:
- $ ./scopes
+```bash
+$ ./scopes
+```
On Windows, and on systems where Scopes has been installed system-wide, it can
be started from the command line without the preceding dot:
- > scopes
+```text
+> scopes
+```
### Interactive Console ###
When `scopes` is launched without arguments, it enters an interactive
read-eval-print loop (REPL), also called a console. Here is an example:
- $ ./scopes
- \\\
- \\\
- ///\\\
- /// \\\ Scopes 0.14 (Apr 17 2019, 19:43:48)
- $0 ▶
+```bash
+$ ./scopes
+ \\\
+ \\\ Scopes 0.14 (Apr 17 2019, 19:43:48)
+ ///\\\ http://scopes.rocks
+/// \\\
+$0 ▶
+```
!!! attention
@@ 49,30 55,36 @@ read-eval-print loop (REPL), also called
Simple expressions can be written on a single line, followed by hitting the
return key:
- $0 ▶ print "hello world"
- hello world
- $0 ▶
+```scopes
+$0 ▶ print "hello world"
+hello world
+$0 ▶
+```
Multiline expressions can be entered by trailing the first line with a space
character, and exited by entering nothing on the last line:
- $0 ▶ print#put a space here
- .... "yes"
- .... "this"
- .... "is"
- .... "dog"
- ....
- yes this is dog
- $0 ▶
+```scopes
+$0 ▶ print#put a space here
+.... "yes"
+.... "this"
+.... "is"
+.... "dog"
+....
+yes this is dog
+$0 ▶
+```
Entering a value binds it to the name indicated by the prompt, and can then
be reused:
- $0 ▶ 3
- $0 = 3
- $1 ▶ print $0
- 3
- $1 ▶
+```scopes
+$0 ▶ 3
+$0 = 3
+$1 ▶ print $0
+3
+$1 ▶
+```
A special keyboard shortcut (`Control+D`) at the prompt exits the program.
You can also exit the program by typing `exit;` followed by hitting the
@@ 84,7 96,9 @@ Most of the time you would like to use S
written Scopes programs. This is simply done by appending the name of the
Scopes file you would like to launch to the executable:
- $ scopes path/to/my/program.sc
+```bash
+$ scopes path/to/my/program.sc
+```
A Fistful of Scopes
-------------------
@@ 95,24 109,28 @@ to the first line starting with a charac
Some examples:
- # this is the first comment
- print "hey!" # and this is a second comment
- and a third, continuing on the same indentation
- let str = "# hash characters inside string quotes do not count as comments"
+```scopes
+# this is the first comment
+print "hey!" # and this is a second comment
+ and a third, continuing on the same indentation
+let str = "# hash characters inside string quotes do not count as comments"
+```
### Using Scopes as a Calculator ###
Scopes is not only a fully-fledged compiler infrastructure, but also works
nicely as a comfy calculator:
- $0 ▶ 1 + 2 + 3
- $0 = 6
- $1 ▶ 23 + 2 * 21
- $1 = 65
- $2 ▶ (23 + 2 * 21) / 5
- $2 = 13.0
- $3 ▶ 8 / 5 # all divisions return a floating point number
- $3 = 1.6
+```scopes
+$0 ▶ 1 + 2 + 3
+$0 = 6
+$1 ▶ 23 + 2 * 21
+$1 = 65
+$2 ▶ (23 + 2 * 21) / 5
+$2 = 13.0
+$3 ▶ 8 / 5 # all divisions return a floating point number
+$3 = 1.6
+```
Integer numbers like `6` or `65` have type `i32`, real numbers with a
fractional part like `13.0` or `1.6` have type `f32`.
@@ 123,6 141,7 @@ fractional part like `13.0` or `1.6` hav
operators and numbers are omitted that the Interactive Console will
display an error when evaluating the expression. For example:
+ :::scopes
$0 ▶ 1+2+3
<string>:1:1: while expanding
1+2+3
@@ 138,14 157,16 @@ Division always returns a real number. O
integer result without the fractional part, use the floor division operator
`//`:
- $0 ▶ 23 / 3 # regular division returns a real
- $0 = 7.666667
- $1 ▶ 23 // 3 # floor division returns an integer
- $1 = 7
- $2 ▶ 23 % 3 # modulo returns the remainder
- $2 = 2
- $3 ▶ $1 * 3 + $2 # result * divisor + remainder
- $3 = 23
+```scopes
+$0 ▶ 23 / 3 # regular division returns a real
+$0 = 7.666667
+$1 ▶ 23 // 3 # floor division returns an integer
+$1 = 7
+$2 ▶ 23 % 3 # modulo returns the remainder
+$2 = 2
+$3 ▶ $1 * 3 + $2 # result * divisor + remainder
+$3 = 23
+```
### Binding Names ###
@@ 153,38 174,44 @@ Notice how the last example leveraged th
console to bind any result to a name for reuse. But we can also make use of
`let` to bind values to specific names:
- $0 ▶ let width = 23
- 23
- $0 ▶ let height = 42
- 42
- $0 ▶ width * height
- $0 = 966
+```scopes
+$0 ▶ let width = 23
+23
+$0 ▶ let height = 42
+42
+$0 ▶ width * height
+$0 = 966
+```
If a name is not bound to anything, using it will give you an error, which is
useful when you've just mistyped it:
- $0 ▶ let color = "red"
- $0 ▶ colour
- <string>:1:1: while expanding
- colour
- error: syntax: identifier 'colour' is not declared in scope. Did you mean 'color'?
+```scopes
+$0 ▶ let color = "red"
+$0 ▶ colour
+<string>:1:1: while expanding
+ colour
+error: syntax: identifier 'colour' is not declared in scope. Did you mean 'color'?
+```
### Strings ###
Life can be tedious and boring at times. Why not perform some string operations
to pass the time? We start with some light declarations of string literals:
- $0 ▶ "make it so" # every string is wrapped in double quotes
- $0 = "make it so"
- $1 ▶ "\"make it so!\", he said" # nested quotes need to be escaped
- $1 = "\"make it so!\", he said"
- $2 ▶ "'make it so!', he said" # single quotes are no problem though
- $2 = "'make it so!', he said"
- $3 ▶ """"1. make it so
- 2. ???
- 3. profit!
- ....
- $3 = "1. make it so\n2. ???\n3. profit!\n"
+```scopes
+$0 ▶ "make it so" # every string is wrapped in double quotes
+$0 = "make it so"
+$1 ▶ "\"make it so!\", he said" # nested quotes need to be escaped
+$1 = "\"make it so!\", he said"
+$2 ▶ "'make it so!', he said" # single quotes are no problem though
+$2 = "'make it so!', he said"
+$3 ▶ """"1. make it so
+ 2. ???
+ 3. profit!
+....
+$3 = "1. make it so\n2. ???\n3. profit!\n"
+```
In the interactive console output, the output string is enclosed in quotes and
special characters are escaped with backslashes, to match the way the string
@@ 192,72 219,84 @@ has been declared. Sometimes this might
but the strings are equivalent. The `print` function produces a more readable
output that produces the intended look:
- $0 ▶ print "make it so"
- make it so
- $0 ▶ print "\"make it so!\", he said"
- "make it so!", he said
- $0 ▶ print """"1. "make it so!", he said
- 2. ???
- 3. profit!"
- ....
- 1. "make it so!", he said
- 2. ???
- 3. profit!
+```scopes
+$0 ▶ print "make it so"
+make it so
+$0 ▶ print "\"make it so!\", he said"
+"make it so!", he said
+$0 ▶ print """"1. "make it so!", he said
+ 2. ???
+ 3. profit!"
+....
+1. "make it so!", he said
+2. ???
+3. profit!
+```
Sometimes it is necessary to join several strings into one. Strings can be
joined with the `..` operator:
- $0 ▶ "Sco" .. "pes" .. "!" # joining three strings together
- $0 = "Scopes!"
- $1 ▶ .. "Sco" "pes" "!" # using prefix notation
- $1 = "Scopes!"
+```scopes
+$0 ▶ "Sco" .. "pes" .. "!" # joining three strings together
+$0 = "Scopes!"
+$1 ▶ .. "Sco" "pes" "!" # using prefix notation
+$1 = "Scopes!"
+```
The inverse operation, slicing strings, can be performed with the `lslice`,
`rslice` and `slice` operations:
- $0 ▶ "scopes" # bind the string we are working on to $0
- $0 = "scopes"
- $1 ▶ rslice $0 1 # slice right side starting at the second character
- $1 = "copes"
- $2 ▶ slice $0 1 5 # slice four letters from the center
- $2 = "cope"
- $3 ▶ lslice $0 ((countof $0) - 1) # a negative index selects from the back
- $3 = "scope"
- $4 ▶ rslice $0 ((countof $0) - 2) # get the last two characters
- $4 = "es"
- $5 ▶ slice $0 2 3 # get the center character
- $5 = "o"
+```scopes
+$0 ▶ "scopes" # bind the string we are working on to $0
+$0 = "scopes"
+$1 ▶ rslice $0 1 # slice right side starting at the second character
+$1 = "copes"
+$2 ▶ slice $0 1 5 # slice four letters from the center
+$2 = "cope"
+$3 ▶ lslice $0 ((countof $0) - 1) # a negative index selects from the back
+$3 = "scope"
+$4 ▶ rslice $0 ((countof $0) - 2) # get the last two characters
+$4 = "es"
+$5 ▶ slice $0 2 3 # get the center character
+$5 = "o"
+```
One way to remember how slices work is to think of the indices as pointing
*between* characters, with the left edge of the first character numbered 0. Then
the right edge of the last character of a string of *n* characters has index *n*,
for example:
- +---+---+---+---+---+---+
- | S | c | o | p | e | s |
- +---+---+---+---+---+---+
- 0 1 2 3 4 5 6
+```text
++---+---+---+---+---+---+
+| S | c | o | p | e | s |
++---+---+---+---+---+---+
+0 1 2 3 4 5 6
+```
If we are interested in the byte value of a single character from a string, we
can use the `@` operator, also called the at-operator, to extract it:
- $0 ▶ "abc" @ 0
- $0 = 97:i8
- $1 ▶ "abc" @ 1
- $1 = 98:i8
- $2 ▶ "abc" @ 2
- $2 = 99:i8
- $3 ▶ "abc" @ ((countof "abc") - 1) # get the last character
- $3 = 99:i8
+```scopes
+$0 ▶ "abc" @ 0
+$0 = 97:i8
+$1 ▶ "abc" @ 1
+$1 = 98:i8
+$2 ▶ "abc" @ 2
+$2 = 99:i8
+$3 ▶ "abc" @ ((countof "abc") - 1) # get the last character
+$3 = 99:i8
+```
The `countof` operation returns the byte length of a string:
- $2 ▶ countof "six"
- $2 = 3:usize
- $3 ▶ countof "three"
- $3 = 5:usize
- $4 ▶ countof "five"
- $4 = 4:usize
+```scopes
+$2 ▶ countof "six"
+$2 = 3:usize
+$3 ▶ countof "three"
+$3 = 5:usize
+$4 ▶ countof "five"
+$4 = 4:usize
+```
### A Mild Breeze of Programming ###
@@ 265,20 304,22 @@ Many calculations require repeating an o
Scopes can also do that. For instance, here is one of the typical examples
for such a task, computing the first few numbers of the fibonacci sequence:
- $0 ▶ loop (a b = 0 1)
- .... if (b < 10)
- .... print b
- .... repeat b (a + b)
- .... else
- .... break b
- ....
- 1
- 1
- 2
- 3
- 5
- 8
- $0 = 13
+```scopes
+$0 ▶ loop (a b = 0 1)
+.... if (b < 10)
+.... print b
+.... repeat b (a + b)
+.... else
+.... break b
+....
+1
+1
+2
+3
+5
+8
+$0 = 13
+```
In Scopes, indentation is how the grouping of statements is determined which
is why the conditional block is indented. A tab or four spaces must start each
@@ 297,6 338,7 @@ This example introduces several new feat
the same time. `a` is initially bound to `0`, while `b` is initialized
to `1`:
+ :::scopes
$0 ▶ loop (a b = 0 1)
* On the second line, we perform a *conditional operation*. That is, the
@@ 304,6 346,7 @@ This example introduces several new feat
expression `(b < 10)` evaluates to `true`. In other words: we are going
to be performing the loop as long as `b` is smaller than `10`:
+ :::scopes
.... if (b < 10)
!!! tip
@@ 316,15 359,18 @@ This example introduces several new feat
* On line 4, the loop will be repeated with `a` bound to the value of `b`,
while `b` will be bound to the result of calculating `(a + b)`:
+ :::scopes
.... repeat b (a + b)
* On line 5, we introduce the alternative block to be executed when `b`
is greater or equal to `10`:
+ :::scopes
.... else
* On line 6, we break from the loop, returning the final value of `b`:
+ :::scopes
.... break b
Controlling Flow
@@ 338,51 384,57 @@ You have seen a small bit of `if` in tha
go-to solution for any task that requires the program to make decisions.
Another example:
- $0 ▶ sc_prompt "please enter a word: " ""
- please enter a word: bang
- $0 $1 = true "bang"
- $2 ▶ if ($1 < "n")
- .... print "early in the dictionary, good choice!"
- .... elseif ($1 == "scopes")
- .... print "oh, a very good word!"
- .... elseif ($1 == "")
- .... print "that is no word at all!"
- .... else
- .... print "late in the dictionary, nice!"
- ....
- early in the dictionary, good choice!
+```scopes
+$0 ▶ sc_prompt "please enter a word: " ""
+please enter a word: bang
+$0 $1 = true "bang"
+$2 ▶ if ($1 < "n")
+.... print "early in the dictionary, good choice!"
+.... elseif ($1 == "scopes")
+.... print "oh, a very good word!"
+.... elseif ($1 == "")
+.... print "that is no word at all!"
+.... else
+.... print "late in the dictionary, nice!"
+....
+early in the dictionary, good choice!
+```
You can also use `if` to decide on an expression:
- $0 ▶ let chosen = true
- true
- $0 ▶ print "you chose"
- .... if x
- .... "poorly"
- .... elseif
- .... "wisely"
- ....
- you chose poorly
+```scopes
+$0 ▶ let chosen = true
+true
+$0 ▶ print "you chose"
+.... if x
+.... "poorly"
+.... elseif
+.... "wisely"
+....
+you chose poorly
+```
### Defining Functions ###
Let us generalize the fibonacci example from earlier to a function that can
write numbers from the fibonacci sequence up to an arbitrary boundary:
- $0 ▶ fn fib (n) # write Fibonacci series up to n
- .... loop (a b = 0 1)
- .... if (a < n)
- .... io-write! (repr a)
- .... io-write! " "
- .... repeat b (a + b)
- .... else
- .... io-write! "\n"
- .... break b
- ....
- fib:Closure
- $0 ▶ fib 2000 # call the function we just defined
- 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
- $0 = 4181
+```scopes
+$0 ▶ fn fib (n) # write Fibonacci series up to n
+.... loop (a b = 0 1)
+.... if (a < n)
+.... io-write! (repr a)
+.... io-write! " "
+.... repeat b (a + b)
+.... else
+.... io-write! "\n"
+.... break b
+....
+fib:Closure
+$0 ▶ fib 2000 # call the function we just defined
+0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
+$0 = 4181
+```
The keyword `fn` introduces a function definition. It must be followed by an
optional name and a list of formal parameters. All expressions that follow
M doc/make.bat +17 -2
@@ 6,7 6,7 @@ if "%MKDOCS%" == "" (
set MKDOCS=mkdocs
)
set BUILDDIR=site
-set MKDOCSOPTS=
+set PYBUILDDIR=site-packages
if "%1" == "" goto help
@@ 15,12 15,15 @@ if "%1" == "help" (
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. clean to discard generated documentation
echo. html to make standalone HTML files
+ echo. serve to start a web server in preview mode for editing
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
+ for /d %%i in (%PYBUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %PYBUILDDIR%\*
goto end
)
@@ 38,11 41,23 @@ if errorlevel 9009 (
)
if "%1" == "html" (
- %MKDOCS% %MKDOCSOPTS% build -d %BUILDDIR%
+ set PYTHONDONTWRITEBYTECODE=1
+ set PYTHONPATH=site-packages;
+ pip install --upgrade -I ./ScopesLexer -t "%PYBUILDDIR%"
+ python -B -m mkdocs build -d "%BUILDDIR%"
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/.
goto end
)
+if "%1" == "serve" (
+ set PYTHONDONTWRITEBYTECODE=1
+ set PYTHONPATH=site-packages;
+ pip install --upgrade -I ./ScopesLexer -t "%PYBUILDDIR%"
+ python -B -m mkdocs serve
+ if errorlevel 1 exit /b 1
+ goto end
+)
+
:end
M doc/mkdocs.yml +4 -2
@@ 22,8 22,10 @@ nav:
- "struct": module-struct.md
- "testing": module-testing.md
- "UTF-8": module-UTF-8.md
-theme: readthedocs
-extra_css: [extra.css]
+theme:
+ name: readthedocs
+ highlightjs: false
+extra_css: [extra.css, pygments.css]
markdown_extensions:
- admonition:
- attr_list:
M lib/scopes/Array.sc +2 -0
@@ 341,10 341,12 @@ let DEFAULT_CAPACITY = (1:usize << 2:usi
To construct a new growing array type:
+ :::scopes
GrowingArray element-type
Instantiate a new array with mutable memory:
+ :::scopes
local new-array : (GrowingArray element-type) [(capacity = ...)]
typedef+ GrowingArray
let parent-type = this-type
M lib/scopes/FunctionChain.sc +2 -1
@@ 11,6 11,7 @@
See following example:
+ :::scopes
using import FunctionChain
# declare new function chain
@@ 37,6 38,7 @@
Running this program will output:
+ :::text
first handler activated with argument 1
handler activated with argument 1
last handler activated with argument 1
@@ 44,7 46,6 @@
handler activated with argument 2
last handler activated with argument 2
handler activated with argument 3
-
typedef FunctionChain : (storageof type)
inline __repr (self)
repr (bitcast self type)
M lib/scopes/String.sc +4 -0
@@ 339,10 339,12 @@ typedef+ StringBase
To construct a new fixed string type:
+ :::scopes
FixedString element-type capacity
Instantiate a new string with mutable memory:
+ :::scopes
local new-string : (FixedString element-type capacity)
typedef+ FixedString
let parent-type = this-type
@@ 418,10 420,12 @@ let DEFAULT_CAPACITY = (1:usize << 2:usi
To construct a new growing string type:
+ :::scopes
GrowingString element-type
Instantiate a new string with mutable memory:
+ :::scopes
local new-string : (GrowingString element-type) [(capacity = ...)]
typedef+ GrowingString
let parent-type = this-type
M lib/scopes/core.sc +7 -1
@@ 81,6 81,7 @@ fn error (msg)
fn error@ (anchor traceback-msg error-msg)
""""usage example:
+ :::scopes
error@ ('anchor value) "while checking parameter" "error in value"
hide-traceback;
let err = (sc_error_new error-msg)
@@ 90,6 91,7 @@ fn error@ (anchor traceback-msg error-ms
fn error@+ (error anchor traceback-msg)
""""usage example:
+ :::scopes
except (err)
error@+ err ('anchor value) "while processing stream"
hide-traceback;
@@ 1236,6 1238,7 @@ sc_typename_type_set_opaque Struct
Here is a typical pattern for constructing a generator:
+ :::scopes
inline make-generator (container)
Generator
inline "start" ()
@@ 1253,6 1256,7 @@ sc_typename_type_set_opaque Struct
The generator can then be subsequently used like this:
+ :::scopes
# this example prints up to two elements returned by a generator
# generate a new instance bound to container
let gen = (make-generator container)
@@ 1270,7 1274,6 @@ sc_typename_type_set_opaque Struct
# container has one more item; print it
print (at state...)
# we are done; no cleanup necessary
-
let Generator = (sc_typename_type "Generator" typename)
'set-plain-storage Generator ('storageof Closure)
@@ 5519,6 5522,7 @@ fn uncomma (l)
""""uncomma list l, wrapping all comma separated symbols as new lists
example:
+ :::scopes
(uncomma '(a , b c d , e f , g h)) -> '(a (b c d) (e f) (g h))
fn comma-separated? (l)
loop (next = l)
@@ 6802,6 6806,7 @@ sugar unlet ((name as Symbol) names...)
Usage example:
+ :::scopes
# add numbers from 0 to 9, skipping number 5, and print the result
print
fold (sum = 0) for i in (range 100)
@@ 7878,6 7883,7 @@ typedef MethodsAccessor
""""This function can be used in conjunction with `from`:
+ :::scopes
from (methodsof <object>) let method1 method2
now the imported methods are implicitly bound to `<object>` and can be
M lib/scopes/testing.sc +2 -0
@@ 169,6 169,7 @@ sugar test-compiler-error (args...)
usage:
+ :::scopes
features B1 B2 B3 ...
---
A1 Y N Y
@@ 177,6 178,7 @@ sugar test-compiler-error (args...)
will expand to:
+ :::scopes
do
Y A1 B1; N A1 B2; Y A1 B3
N A2 B1; Y A2 B2; N A2 B3