diff --git a/gazprea/impl/backend.rst b/gazprea/impl/backend.rst index cd45e19..cd265e9 100644 --- a/gazprea/impl/backend.rst +++ b/gazprea/impl/backend.rst @@ -47,7 +47,7 @@ name mangling that occurs to allow class functions. Thus, we recommend that all runtime functions should be written in C and not in C++. There is a Makefile in the ``runtime`` folder designed to turn all ``*.c`` and ``*.h`` pairs into part of the unified runtime library ``libruntime.a``. -An example of how to make a runtime function is provided bellow. +An example of how to make a runtime function is provided below. ``functions.c`` diff --git a/gazprea/impl/errors.rst b/gazprea/impl/errors.rst index 349a040..f5e65e6 100644 --- a/gazprea/impl/errors.rst +++ b/gazprea/impl/errors.rst @@ -13,7 +13,7 @@ new errors. Your compiler is only expected to report the first error it encounters. Syntax Errors -~~~~~~~~~~~~~ +------------- ANTLR handles syntax errors automatically, but you are required to override the behavior and throw the ``SyntaxError`` exception from @@ -80,7 +80,7 @@ Here are the compile-time errors your compiler must throw: * ``TypeError`` Raised during compilation if an operation or statement is applied to or - betweeen expressions with invalid or incompatible types. + between expressions with invalid or incompatible types. * ``AliasingError`` @@ -102,7 +102,7 @@ Here are the compile-time errors your compiler must throw: Raised during compilation if the program detects a function or procedure with a return value that does not have a return statement reachable by all - control flows. Control flow constructs may be assumed to always be undecideable, + control flows. Control flow constructs may be assumed to always be undecidable, meaning they may branch in either direction. If the subroutine has a ``return`` statement with a type that does not @@ -146,7 +146,7 @@ Here are the compile-time errors your compiler must throw: * ``MathError`` May be raised during compile time expression evaluation when division by zero occurs. - Conditions for raising are eqivalent to a runtime ``MathError``. + Conditions for raising are equivalent to a runtime ``MathError``. * ``IndexError`` @@ -155,10 +155,9 @@ Here are the compile-time errors your compiler must throw: * ``SizeError`` - May be aised during compilation if the compiler detects an operation or statement + May be raised during compilation if the compiler detects an operation or statement is applied to or between arrays with invalid or incompatible - sizes. Read more about when a ``SizeError`` should be raised at run-time - instead of compile-time in the :ref:`ssec:errors_sizeErrors` section. + sizes. * ``StrideError`` @@ -190,7 +189,7 @@ Run-time errors must be handled by calling the functions defined in The runtime errors listed below are a subset of compile time errors. Since it is not only impractical, but undecidable to catch the following errors exclusively at compile time, Gazprea leaves the setting at which they are raised up to the implementation. To put simply, you can raise runtime errors either -at compile time or at runtime and the tester will accomodate to different implementations. +at compile time or at runtime and the tester will accommodate different implementations. * ``SizeError`` @@ -213,7 +212,7 @@ at compile time or at runtime and the tester will accomodate to different implem ``<=0``. Here is an example invalid program. If your compiler is smart, you may raise the later error, if you -perfer not to implement static analysis, the former error can be emited at runtime. +prefer not to implement static analysis, the former error can be emitted at runtime. :: @@ -240,12 +239,12 @@ More Examples character[3] v = ['a', 'b', 'c']; // Indexing is harder than it looks! integer i = 10; v(3) = 'X'; // SyntaxError - v[i] = '?'; // Run-timeerror + v[i] = '?'; // Runtime error v['a'] = '!'; // TypeError i[1] = 1; // SymbolError /* Tuples */ - tuple (integerm integer) a = (9, 5); + tuple (integer, integer) a = (9, 5); integer b; integer c; integer d; @@ -312,7 +311,7 @@ Additionally, the tester only knows to stop the toolchain prematurely if your pr terminates with a non-zero exit code. Once you have caught an error make sure to return a non-zero exit code. -Finally, the tester is lenient towards the type given to a particular errror. Specifically +Finally, the tester is lenient towards the type given to a particular error. Specifically the tester simply confirms that the substring "Error" is present and for compile time errors that the correct line is provided. diff --git a/gazprea/impl/part_1.rst b/gazprea/impl/part_1.rst index e1833b2..db2509e 100644 --- a/gazprea/impl/part_1.rst +++ b/gazprea/impl/part_1.rst @@ -6,7 +6,7 @@ Compiler Implementation — Part 1 This section lists the portions of the *Gazprea* specification that must be implemented to complete the part 1 of the compiler implementation. All developers are advised to read the full specification for the -language prior to start the implementation of Part 1 because decisions +language prior to starting the implementation of Part 1 because decisions made while implementing Part 1 can make the implementation of Part 2 significantly more challenging. Thus, planning ahead for Part 2 is the recommended strategy. diff --git a/gazprea/impl/part_2.rst b/gazprea/impl/part_2.rst index 8aaf319..fb4da42 100644 --- a/gazprea/impl/part_2.rst +++ b/gazprea/impl/part_2.rst @@ -1,7 +1,7 @@ Compiler Implementation — Part 2 ================================ -This section list the elements of the *Gazprea* specification that must +This section lists the elements of the *Gazprea* specification that must be completed for the Part 2 of the compiler implementation. All the elements of Part 1 must have been completed because Part 2 builds on Part 1. diff --git a/gazprea/index.rst b/gazprea/index.rst index 54a4f74..5eda096 100644 --- a/gazprea/index.rst +++ b/gazprea/index.rst @@ -18,6 +18,7 @@ Hardware Acceleration Laboratory in Markham, ON. spec/keywords spec/identifiers + spec/namespaces spec/comments spec/declarations spec/type_qualifiers diff --git a/gazprea/spec/built_in_functions.rst b/gazprea/spec/built_in_functions.rst index 3d1fdb0..b89580a 100644 --- a/gazprea/spec/built_in_functions.rst +++ b/gazprea/spec/built_in_functions.rst @@ -58,8 +58,8 @@ reversed version of it. integer[*] v = 1..5; integer[*] w = reverse(v); - v -> std_output; /* Prints 12345 */ - w -> std_output; /* Prints 54321 */ + v -> std_output; /* Prints [1, 2, 3, 4, 5] */ + w -> std_output; /* Prints [5, 4, 3, 2, 1] */ .. _ssec:builtIn_format: @@ -95,7 +95,7 @@ implicitly defined in every file: procedure stream_state(var input_stream) returns integer; -This function can only be called with the ``std_input`` as a parameter, but it’s +This procedure can only be called with the ``std_input`` as a parameter, but it’s general enough that it could be used if the language were expanded to include multiple input streams. diff --git a/gazprea/spec/expressions.rst b/gazprea/spec/expressions.rst index bde026d..1342e07 100644 --- a/gazprea/spec/expressions.rst +++ b/gazprea/spec/expressions.rst @@ -127,7 +127,7 @@ commas, such as in matrix generators. /* The "i"s both domain expressions are at the same scope, which is * the one enclosing the loop. Therefore the matrix is: [[0 0 0] [0 1 2] [0 2 4]] */ - integer[3,3] mat = [ i in 0..i, j in 0..i | i*j ]; + integer[3][3] mat = [ i in 0..i, j in 0..i | i*j ]; The domain for the domain expression is only evaluated once. For instance: diff --git a/gazprea/spec/functions.rst b/gazprea/spec/functions.rst index 5cc1403..f073f21 100644 --- a/gazprea/spec/functions.rst +++ b/gazprea/spec/functions.rst @@ -198,7 +198,7 @@ Like Rust, array *slices* may be passed as arguments: Remember that all function parameters are ``const`` in *Gazprea*, so that all functions are pure. That means that while it is legal to pass arrays and slices -*be reference*, the array contents cannot be modified inside the function, +*by reference*, the array contents cannot be modified inside the function, because the change would be visible outside the function. You must check that the ``const`` requirement is honored. @@ -211,10 +211,5 @@ In *Gazprea* function declarations occur in the global scope. This means that two functions with the same name cannot coexist in the same gazprea program, nor can you forward declare the same function twice. -Additionally, functions share the following namespaces: - -- The ``struct`` namespace: you cannot have a struct and function with the same - name in the same gazprea program. - -- The ``procedure`` namespace: You cannot have a procedure and function with - the same name in the same gazprea program. +Additionally, functions and procedures share the same namespace; you cannot +declare a function and procedure with the same name diff --git a/gazprea/spec/globals.rst b/gazprea/spec/globals.rst index ee294a4..453676f 100644 --- a/gazprea/spec/globals.rst +++ b/gazprea/spec/globals.rst @@ -3,7 +3,7 @@ Globals ======= -Valid global scope statements inclulde: +Valid global scope statements include: * Variable Declarations * Struct Declarations @@ -15,7 +15,7 @@ All global statements are considered declarations. Global statements may occur in any order, given respective symbols are defined before being referenced. Variable Declarations -===================== +--------------------- In *Gazprea* values can be assigned to a global identifier. All globals must be immutable (``const``). If a global identifier is declared with diff --git a/gazprea/spec/identifiers.rst b/gazprea/spec/identifiers.rst index 4e742da..3b15e26 100644 --- a/gazprea/spec/identifiers.rst +++ b/gazprea/spec/identifiers.rst @@ -31,33 +31,3 @@ a number, contain invalid characters, or are a keyword: *Gazprea* imposes no restrictions on the length of identifiers. -.. _ssec:namespace: - -Namespaces -========== - -Identifiers are used by variables, user-defined types, functions and procedures. - -For the most part, user-defined types are in their own namespace because their -usage does not collide with variables or functions. -The one exception is that struct literals can look like function calls: - -:: - - struct A (integer i, real j); - A a = A(i, j); - -Consequently, struct literals and functions share the same namespace. -In the above example, a definition of function ``A`` should generate a -``SymbolError``, but a definition of variable ``A`` would not. -Outside of types, variables and functions/procedures share the same namespace -in a scope and shadowing is possible between these types. - -:: - - function x() returns integer; // "x" refers to this function in the global scope - - procedure main() { - integer x = 3; // "x" refers to this variable in the scope of main - } - ... diff --git a/gazprea/spec/namespaces.rst b/gazprea/spec/namespaces.rst new file mode 100644 index 0000000..34317d3 --- /dev/null +++ b/gazprea/spec/namespaces.rst @@ -0,0 +1,42 @@ +.. _sec:namespaces: + +Namespaces +========== + +There are two namespaces in *Gazprea*: + +- Type namespace: user-defined types (structs and typealiases). +- Variable/Function/procedure namespace: functions and procedures. + +Items in separate namespaces may share an identifier. Items within the same namespace cannot share an identifier, this is a ``SymbolError``. + +:: + + // Does not conflict with the other statements + struct x (integer a, integer b); + + // These three statements all confict with each other + // Any two of them in the same program produces a SymbolError + integer x = 3; + function x() returns integer; + procedure x() returns integer; + +:: + + // Pro tip: write code that looks like this, employers love it + + typealias integer a; + typealias integer main; // Procedure and type do not conflict + struct b (a b, a a, main main); // Struct field identifiers do not conflict with anything + + procedure main() returns integer { + + a a = 1; // type and variable do not conflict + + b b = b(b: a, a: 2, main: 3); + + if (true) { // New scope + a a = b.b // New `a` shadows the old `a` + } + return 0; + } diff --git a/gazprea/spec/procedures.rst b/gazprea/spec/procedures.rst index af95cdb..950b03f 100644 --- a/gazprea/spec/procedures.rst +++ b/gazprea/spec/procedures.rst @@ -77,7 +77,7 @@ These procedures can be called as follows: call increment(x); /* x == 13 */ call fibonacci(x,y); /* x == 21 and y == 34 */ -It is only possible to call procedures in this way. Functions must +Only procedures may be called with ``call``. Functions must appear in expressions because they can not cause side effects, so using a function in a ``call`` statement would not do anything. *Gazprea* should raise an error if a function is used in a ``call`` statement. @@ -235,21 +235,17 @@ Array Parameters and Returns value of procedures can have both explicit and inferred sizes. Similarly, slices can be used whereever arrays are declared as parameters, and -unlike functions, array parameters in procedures can be ``var``. +unlike functions, array parameters in procedures can be ``var``, allowing arrays +and slices passed to a procedure to be modified (see :ref:`sssec:array_slices`). -.. _ssec:function_namespacing: +.. _ssec:procedure_namespacing: Procedure Namespacing --------------------- +--------------------- In *Gazprea* procedure declarations occur in the global scope. This means that two procedures with the same name cannot coexist in the same gazprea program, nor can you forward declare the same procedure twice. -Additionally, procedures share the following namespaces: - -- The ``struct`` namespace: you cannot have a struct and function with the same - name in the same gazprea program. - -- The ``function`` namespace: You cannot have a procedure and function with - the same name in the same gazprea program. +Additionally, functions and procedures share the same namespace; you cannot +declare a function and procedure with the same name diff --git a/gazprea/spec/streams.rst b/gazprea/spec/streams.rst index 610ca35..c788736 100644 --- a/gazprea/spec/streams.rst +++ b/gazprea/spec/streams.rst @@ -4,7 +4,7 @@ Streams ======= *Gazprea* has two streams: ``std_output`` and ``std_input``, -which are used for writting to `stdout` and reading from `stdin` respectively. +which are used for writing to `stdout` and reading from `stdin` respectively. .. _ssec:output: @@ -145,15 +145,15 @@ must be readable. An ``integer`` from stdin can take any legal format described in the :ref:`integer literal ` section. It may also be preceded by -a single negative or positive sign. All preceeding whitespace before the number or +a single negative or positive sign. All preceding whitespace before the number or sign character may be skipped up to the limit imposed by the 512 byte read restriction. A ``real`` input from stdin can take any legal format described in the :ref:`real literal ` section with the exception that no -whitespace may be present. It may also be proceeded by a single negative or -positive sign. Preceeding whitespace may be skipped in the same way as integers. +whitespace may be present. It may also be preceded by a single negative or +positive sign. Preceding whitespace may be skipped in the same way as integers. -A ``boolean`` input from stdin is either ``T`` or ``F``. Preceeding whitespace may be +A ``boolean`` input from stdin is either ``T`` or ``F``. Preceding whitespace may be skipped in the same way as integers and reals. For the following program: @@ -203,8 +203,8 @@ Reading a ``character`` can never cause an error. The character will either be successfully read or the end of the stream will be reached and ``-1`` will be returned on this read. -When an error occurs the the null value is assigned and the input stream -remains pointing to the same position as before the read occured. +When an error occurs the null value is assigned and the input stream +remains pointing to the same position as before the read occurred. The program below demonstrates 4 reads which set the error states 1,0,0,2 respectively. diff --git a/gazprea/spec/type_promotion.rst b/gazprea/spec/type_promotion.rst index c5a6325..4d51dbc 100644 --- a/gazprea/spec/type_promotion.rst +++ b/gazprea/spec/type_promotion.rst @@ -23,7 +23,7 @@ converted to ``integer``. Automatic type conversion follows this table where N/A means no implicit conversion possible, id means no conversion necessary, ``as(var)`` means var of type "From type" is converted to type -"toType" using semantics from . +"toType" using semantics from :ref:`sec:typeCasting`. +----------+-----------+---------+-----------+---------+---------------+ | | **To type** | diff --git a/gazprea/spec/typedef.rst b/gazprea/spec/typedef.rst index 754edad..a533600 100644 --- a/gazprea/spec/typedef.rst +++ b/gazprea/spec/typedef.rst @@ -14,7 +14,7 @@ new name to refer to the old type. For instance: typealias integer int; const int a = 0; -Note that hese new type names can *appear* to conflict with symbol names. +Note that these new type names can *appear* to conflict with symbol names. However, the compiler can use context to differentiate a type alias from a symbol. The following is therefore legal: @@ -64,7 +64,7 @@ Duplicate alias names should raise a `SymbolError` Some type aliases may be parameterized with an expression, such as with arrays, such expressions are restricted to be composed exclusively from arithmetic operations on scalar literals. Practically speaking, this requires constant -folding but *not* constant propogation. +folding but *not* constant propagation. :: diff --git a/gazprea/spec/types/array.rst b/gazprea/spec/types/array.rst index a0ad9db..329d831 100644 --- a/gazprea/spec/types/array.rst +++ b/gazprea/spec/types/array.rst @@ -1,7 +1,7 @@ .. _ssec:array: Arrays -------- +------ Arrays are fixed size collections, where each element of the array has the same type. Arrays can contain any of *Gazprea*'s base types (``boolean``, @@ -48,8 +48,7 @@ array instead of a ``real`` array. If the LHS array is initialized using a RHS array that is too small then the LHS array will be padded with zeros. However, if the LHS array is initialized with a RHS array that is too large then a ``SizeError`` should be thrown at - compile-time or run-time. Check the :ref:`ssec:errors_sizeErrors` section to know when you - should throw the error. + compile-time or run-time. #. Inferred Size Declarations @@ -278,7 +277,7 @@ Operations e. Stride The ``by`` operator is used to specify a step-size greater than 1 when - indexing across an array. It produces a new array with the values + indexing across an array. It produces an array with the values indexed by the given stride. For instance: :: @@ -299,7 +298,7 @@ Operations integer[*] a = 0..10 by 2; /* a = [0, 2, 4, 6, 8, 10] */ integer[2] x = a[2..4]; /* x == [2, 4] */ - Note that for slices only a stride of 1 is allowed. + Note that for slicing with this syntax always has a stride of 1. For indexing purposes three additions are made to range syntax: +---------+---------------------------------+ @@ -313,14 +312,16 @@ Operations +---------+---------------------------------+ + `i..j` | i to jth elements | +---------+---------------------------------+ + Examples: :: integer[*] a = 0..10 by 2; /* a = [0, 2, 4, 6, 8, 10] */ integer x = a[..4]; /* x == [0, 2, 4] */ - integer y = a[4..]; /* x == [6, 8, 10] */ - integer z = a[..-1]; /* x == [0, 2, 4, 6, 8] */ + integer y = a[4..]; /* y == [6, 8, 10] */ + integer z = a[..-1]; /* z == [0, 2, 4, 6, 8] */ + #. Operations of the Element Type @@ -394,6 +395,64 @@ Operations The ``!=`` operation also produces a boolean instead of a boolean array. The result is the logical negation of the result of the ``==`` operator. +.. _sssec:array_slices: + +Array Slices +~~~~~~~~~~~~ + +An array may be indexed by a range to create a new array that is a *slice* +of the original. An array slice behaves semantically as an array containing +the array elements captured by the slice, as shown below. + +:: + + // 0..10 is a range, not a slice + integer[*] a = 0..10 by 2; /* a = [0, 2, 4, 6, 8, 10] */ + integer[2] x = a[2..4]; /* x == [2, 4] */ + integer y = a[2..4][1]; /* y == 2 */ + + // A slice of the entire array behaves as the array itself, this can be repeated + integer z1 = a[4]; /* z1 == 6 */ + integer z2 = a[1..7][1..7][1..7][4]; /* z2 == 6 */ + + +Array slices have special behaviour when they are used in a parameter call +or on the left side of an assignment, where they allow modification of the +source array: + + +:: + + procedure sum_arrays(const integer[*] in1, const integer[*] in2, var integer[*] out) { + /* sum the two inputs and fill the output with the result */ + } + + procedure main() returns integer { + + integer[6] a = 0..10 by 2; /* a = [0, 2, 4, 6, 8, 10] */ + integer[6] b = 0..15 by 3; /* b = [0, 3, 6, 9, 12, 15] */ + var integer[6] c; /* c must be var */ + + /* procedure works normally with an array */ + call sum_arrays(a, b, c); + c -> std_output; /* [0, 5, 10, 15, 20, 25] */ + + /* procedure can also modify a slice */ + call sum_arrays(a[1..4], b[1..4], c[4..7]); + c -> std_output; /* [0, 5, 10, 0, 5, 10] */ + + /* slice can be assigned to, modifying c */ + c[3..5] = [415, 429]; + c -> std_output; /* [0, 5, 415, 429, 5, 10] */ + + return 0; + } + +This behaviour is consistent with the slice being thought of as a +reference to the original array's elements, where in the first +examples, the assignments perform a deep copy as usual and in the +procedure example, the parameters are passed by reference as usual. + Type Casting and Type Promotion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/gazprea/spec/types/matrix.rst b/gazprea/spec/types/matrix.rst index 00ac607..15c4b1b 100644 --- a/gazprea/spec/types/matrix.rst +++ b/gazprea/spec/types/matrix.rst @@ -97,12 +97,12 @@ matrix respectively. For instance: integer[*][*] M = [[1, 1, 1], [1, 1, 1]]; integer r = rows(M); /* This has a value of 2 */ - integer c = columns(M); /* This has a value of 3 \*/ + integer c = columns(M); /* This has a value of 3 */ Matrix indexing is done similarly to array indexing, however, two indices must be used. Because matrices are arrays of arrays the indexing is -coposite: +composite: :: diff --git a/gazprea/spec/types/string.rst b/gazprea/spec/types/string.rst index 664f9b7..916ad09 100644 --- a/gazprea/spec/types/string.rst +++ b/gazprea/spec/types/string.rst @@ -21,7 +21,7 @@ Declaration A string may be declared with the keyword ``string``. The same rules of :ref:`vector declarations ` also apply to strings, which means -that all lenghts are inferred: +that all lengths are inferred: :: @@ -48,7 +48,7 @@ differently by the compiler: character[*] carray = ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\n']; string vec = carray; - carry -> std_output; + carray -> std_output; vec -> std_output; prints: diff --git a/gazprea/spec/types/struct.rst b/gazprea/spec/types/struct.rst index 5a0a424..75457cd 100644 --- a/gazprea/spec/types/struct.rst +++ b/gazprea/spec/types/struct.rst @@ -27,12 +27,12 @@ and consist of a ```` pair: struct Another (character char, real float, string[256] str, s1 struct_field); var Another t2; -The examples show two structs declared with types ``s1`` and ``another``. +The examples show two structs declared with types ``s1`` and ``Another``. Struct type ``s`` has three fields: ``i`` of type ``integer``, ``r`` of type ``real``, and ``iv`` of type ``integer[10]``. -Struct type ``another`` has four fields named ``char``, ``float``, ``str``, +Struct type ``Another`` has four fields named ``char``, ``float``, ``str``, and ``struct_field``. -The instance variables are ``t1`` and ``t2`` have types ``s1`` and ``another``, +The instance variables ``t1`` and ``t2`` have types ``s1`` and ``Another``, respectively. @@ -49,7 +49,7 @@ A struct can be typealiased and used in any context a regular struct declaration typealias struct S(integer x, integer y) Pair; function add(Pair p1, Pair p2) returns Pair { - Pair p3 = S(p1.x + p2.x, p1.y + p2.y); // Pair can not be used in place of S + Pair p3 = S(x: p1.x + p2.x, y: p1.y + p2.y); // Pair can not be used in place of S return p3; } @@ -83,22 +83,22 @@ or right hand side of an expression: Literals ~~~~~~~~ -A ``struct`` literal is constructed by listing comma separated values for each -field in the struct, in the order defined in the struct's definition. -The value list is surrounded by parenthesis and prefaced by the struct type: +A ``struct`` literal is constructed by listing comma separated ``field: value`` +pairs for each field in the struct, surrounded by parentheses and prefaced by +the struct type name: :: struct S (integer i, character[5] c, integer[3] a3); - const S cs = S(x, "hello", [1, 2, 3]); - var S vs = S(0, ' ', 0); - struct V (integer i, real r, integer[10] arr) v = V(1, 2.1, [i in 1..10 | i]); + const S cs = S(i: x, c: "hello", a3: [1, 2, 3]); + var S vs = S(c: ' ', i: 0, a3: 0); + struct V (integer i, real r, integer[10] arr) v = V(i: 1, r: 2.1, arr: [i in 1..10 | i]); -The type of each value in the list must match the type of the corresponding -field definition in the struct. To save having to explicitly specify a value -for each index in an array, *Gazprea* allows a single scalar to be propagated -across all elements in the array. Finally, note that the field values may need -to be evaluated at run-time. +The fields may be listed in any order, but all fields must be present. The type +of each value must match the type of the corresponding field definition in the +struct. To save having to explicitly specify a value for each index in an array, +*Gazprea* allows a single scalar to be propagated across all elements in the +array. Finally, note that the field values may need to be evaluated at run-time. .. _sssec:struct_ops: @@ -126,8 +126,8 @@ This allows struct instances to be compared to struct literals: :: - struct Complex (real r, real i) c = Complex(r, 0.0); - if (c == Complex(0.0, i)) { } + struct Complex (real r, real i) c = Complex(r: r, i: 0.0); + if (c == Complex(r: 0.0, i: i)) { } Two structs are equal when all fields within each struct have the same value. It is an error to compare two structs of different types. @@ -139,19 +139,11 @@ A struct itself cannot be cast or promoted. However, the fields within a struct can be individually cast/promoted, as described in sections :ref:`sec:typeCasting` and :ref:`sec:typePromotion`. -.. _ssec:function_namespacing: +.. _ssec:struct_namespacing: Struct Namespacing --------------------- +~~~~~~~~~~~~~~~~~~ In *Gazprea*, struct declarations can occur in *any* scope. This means that two struct types with the same name *can* coexist in the same gazprea program so long as they are not in the same scope - -Additionally, ``structs`` share the following namespaces: - -- The ``procedure`` namespace: You cannot have a procedure and struct with - the same name in the same gazprea program. - -- The ``function`` namespace: You cannot have a function and struct with - the same name in the same gazprea program. diff --git a/gazprea/spec/types/tuple.rst b/gazprea/spec/types/tuple.rst index 99cf664..ed0e759 100644 --- a/gazprea/spec/types/tuple.rst +++ b/gazprea/spec/types/tuple.rst @@ -116,7 +116,7 @@ Unpacking Any tuple expression may be assigned (unpacked) into multiple lvalues. If the size of the tuple being unpacked does not match the number of lvalues being asigned, an ``AssignError`` -may be raised. There is no partial unpacking of tuples. +is raised. There is no partial unpacking of tuples. :: diff --git a/gazprea/spec/types/vector.rst b/gazprea/spec/types/vector.rst index ff42f8a..a6586a0 100644 --- a/gazprea/spec/types/vector.rst +++ b/gazprea/spec/types/vector.rst @@ -34,7 +34,9 @@ specifier, often called *capacity* in other languages. Below are some examples o const vector v1 = 3; // [[3, 3]] const vector v2 = [4, 5]; // [[4, 5]] const vector v3 = 42; // [42] - const vector v4 = 1; // [1.0] + var vector v4 = 42; // [42], mutable + vector v4 = 42; // [42], implied const + const vector v5 = 1; // [1.0] Vectors of inferred sized arrays assume the size of the *first* array in the vector. @@ -45,7 +47,7 @@ Those greater raise a runtime ``SizeError``. const vector vec = ['a', 'b', 'c']; const vector ragged_right = [[1.0], [2.0, 2.0]]; // SizeError - const vector paddeded_right = [[1.0, 2.0], [1.0]]; // Padds second element + const vector padded_right = [[1.0, 2.0], [1.0]]; // Pads second element const vector const_vec = vec; @@ -54,51 +56,47 @@ Operations Operations on vectors are identical syntactically and semantically to operations on arrays. In particular, operand lengths must match for binary -expressions and dot product. Vectors can behave as arrays by using slices: +expressions and dot product. All binary operations between vector and arrays produce array results. - :: - - var vector v1, v2; - var integer[3] a; - v1.append([1, 2, 3]); - a = v1; // slice of v yields array and can be used to initialize 'a' - v2 = v1 + a; // slice of vector plus array yields result type array - a = v1 + v2; // slice of v1 + slice of v2 still yields array type - - -A vector or vector slice can be passed as a call argument that has been -declared as an array slice of the same size and type. When indexing a vector of arrays, -the first index selects the array element within the vector, and the second index selects -the element within the array: +As a language supported object, *Gazprea* provides several methods for ``vector``: - :: +- ``push(T)`` - pushes a new element to the back of the vector, where ``T`` is the element type of the vector - vector ragged_right = [[1.0], [2.1]]; - length(ragged_right[1]) -> std_output; // prints 1 - ragged_right[2][1] -> std_output; // prints 2.1 +- ``len()`` - number of elements in the vector +- ``append(T[*])`` - append another array to the vector where ``T[*]`` is the type of the original vector or a type that can be implicitly cast to it. -As a language supported object, *Gazprea* provides several methods for ``vector``: + :: -- ``push()`` - pushes a new element to the back of the vector + var vector v1; // v1 == [] + v1.len() -> std_output; // 0 -- ``len()`` - number of elements in the vector + v1.push(1); // v1 == [1] + v1.len() -> std_output; // 1 -- ``append(T[*])`` - append another array slice to the vector where `T` is the type of the original vector or a type that can be implicitly cast to it. The following example tracks the elements inside `vec` through various appends. + v1.push(2); // v1 == [1, 2] + v1.len() -> std_output; // 2 - :: + v1.append([3, 4, 5]) // v1 == [1, 2, 3, 4, 5] + v1.len() -> std_output; // 5 + var vector v2; // v2 == [] const x = 1..10; - var vector vec; // [] - // scalar to array promotion - vec.append(1); // [[1.0, 1.0]] + // `1` is promoted to `[1.0, 1.0]` before appending + v2.append(1); // v2 == [[1.0, 1.0]] - // array padding - vec.append(3..3); // [[1,0, 1.0], [3.0, 0.0]] + // length 1 array padded to length 2 + v2.append([3.0]); // v2 == [[1.0, 1.0], [3.0, 0.0]] // slices - vec.append(x[5..7]); // [[1,0, 1.0], [3.0, 0.0], [5.0, 6.0]] + v2.append(x[5..7]); // v2 == [[1.0, 1.0], [3.0, 0.0], [5.0, 6.0]] - vec[tvec.len()] -> std_output; // prints 3 + v2.len() -> std_output // 3 + +Slicing a vector produces an array slice (there are no "vector slices"). + + :: + // Slicing a vector produces an array slice + vec[2..5].append(x[5..7]) // TypeError; cannot do `append` on an array slice