diff options
| -rw-r--r-- | .editorconfig | 1 | ||||
| -rw-r--r-- | _ext/crowbar_domain.py | 2 | ||||
| -rw-r--r-- | _ext/gemtext_builder.py | 30 | ||||
| -rw-r--r-- | index.rst | 2 | ||||
| -rw-r--r-- | language/functions.rst | 30 | ||||
| -rw-r--r-- | language/include.rst | 7 | ||||
| -rw-r--r-- | language/index.rst | 3 | ||||
| -rw-r--r-- | language/scanning.rst | 24 | ||||
| -rw-r--r-- | language/source-file.rst | 4 | ||||
| -rw-r--r-- | language/statements/index.rst | 23 | ||||
| -rw-r--r-- | language/statements/structure.rst | 21 | ||||
| -rw-r--r-- | language/statements/variables.rst | 24 | ||||
| -rw-r--r-- | language/type-definition.rst | 12 | ||||
| -rw-r--r-- | make.bat | 70 | ||||
| -rw-r--r-- | safety.rst | 2 | ||||
| -rw-r--r-- | syntax.md | 20 | ||||
| -rw-r--r-- | vs-c.rst | 2 | 
17 files changed, 181 insertions, 96 deletions
diff --git a/.editorconfig b/.editorconfig index f4dfbaa..f7a7f0f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,6 +6,7 @@ insert_final_newline = true  indent_style = space  indent_size = 4  charset = utf-8 +trim_trailing_whitespace = true  [Makefile]  indent_style = tab diff --git a/_ext/crowbar_domain.py b/_ext/crowbar_domain.py index 619487d..673f756 100644 --- a/_ext/crowbar_domain.py +++ b/_ext/crowbar_domain.py @@ -52,7 +52,7 @@ class ElementDirective(ObjectDescription):                  else:                      peg_rule += addnodes.desc_sig_operator('', '', nodes.literal(text=token))          return element -     +      def add_target_and_index(self, name, sig, signode):          signode['ids'].append('element' + '-' + name)          if 'noindex' not in self.options: diff --git a/_ext/gemtext_builder.py b/_ext/gemtext_builder.py index c26b053..9c7326d 100644 --- a/_ext/gemtext_builder.py +++ b/_ext/gemtext_builder.py @@ -14,7 +14,7 @@ class GemtextWriter(writers.Writer):      def __init__(self, builder):          super().__init__()          self.builder = builder -     +      def translate(self):          visitor = self.builder.create_translator(self.document, self.builder)          self.document.walkabout(visitor) @@ -33,25 +33,25 @@ class GemtextTranslator(SphinxTranslator):          if self.current_line != '':              self.body.append(self.current_line)              self.current_line = '' -     +      def visit_document(self, node: nodes.document):          self.heading_level = 1          self.current_line = ''          self.body = []          self.literal = False          self.pending_links = [] -     +      def depart_document(self, node: nodes.document):          self._finish_line() -     +      def visit_section(self, node: nodes.section):          self.heading_level += 1          if len(self.body) > 0 and self.body[-1] != '':              self.body.append('') -     +      def depart_section(self, node: nodes.section):          self.heading_level -= 1 -     +      def visit_title(self, node: nodes.title):          pass @@ -65,7 +65,7 @@ class GemtextTranslator(SphinxTranslator):          if not self.literal:              text = text.replace('\n', ' ')          self.current_line += text -     +      def depart_Text(self, node: nodes.Text):          pass @@ -95,7 +95,7 @@ class GemtextTranslator(SphinxTranslator):              self.body.append('=> {} {}'.format(node.attributes['uri'], node.attributes['alt']))          else:              raise NotImplementedError('inline images') -     +      def depart_image(self, node: nodes.image):          pass @@ -104,12 +104,12 @@ class GemtextTranslator(SphinxTranslator):      def visit_strong(self, node: nodes.strong):          self.current_line += '**' -     +      depart_strong = visit_strong      def visit_emphasis(self, node: nodes.emphasis):          self.current_line += '_' -     +      depart_emphasis = visit_emphasis      def visit_target(self, node: nodes.target): @@ -165,16 +165,16 @@ class GemtextTranslator(SphinxTranslator):          self.body.append('```')          self.body.append('')          self.literal = False -     +      def visit_index(self, node: nodes.Node):          pass -     +      def depart_index(self, node: nodes.Node):          pass      def visit_desc(self, node: nodes.Node):          pass -     +      def depart_desc(self, node: nodes.Node):          pass @@ -250,10 +250,10 @@ class GemtextBuilder(Builder):      def get_outdated_docs(self):          yield from self.env.found_docs # can't be fucked to implement this right          yield 'genindex' -     +      def get_target_uri(self, docname: str, typ: str = None):          return docname + '.gmi' -     +      def prepare_writing(self, docnames: Set[str]):          self.writer = GemtextWriter(self) @@ -48,7 +48,7 @@ Chapters  ========  ..  toctree:: -    :maxdepth: 1 +    :maxdepth: 2      :numbered:      vs-c diff --git a/language/functions.rst b/language/functions.rst index 86d1144..22a61a3 100644 --- a/language/functions.rst +++ b/language/functions.rst @@ -3,18 +3,36 @@ Functions  .. crowbar:element:: FunctionDeclaration <- FunctionSignature ';' -    A function declaration defines the return type, name, and arguments of a function without specifying its behavior. -    It is generally used as part of an API boundary. +    Compile-time Behavior: + +    Provides a declaration of a function with the name, return type, and arguments specified by the signature, but does not specify any behavior. +    This is generally used as part of an API boundary. + +    Runtime Behavior: + +    A function declaration has no runtime behavior.  .. crowbar:element:: FunctionDefinition <- FunctionSignature Block -    A function definition provides the actual behavior of a function, which may have been declared previously or may not. +    Compile-time Behavior: + +    Provides the actual behavior of a function, which may have been declared previously or may not. +    If the function was declared in some ``.hro`` file which was :crowbar:ref:`include <IncludeStatement>`\ d, the function must be exported and available for external use in the compiler's output. +    Otherwise, the function should not be exported. + +    If the function signature specifies a return type other than ``void``, but there are paths through the block that do not execute a :crowbar:ref:`ReturnStatement`, the compiler must give an error. -    .. todo:: +    Runtime Behavior: -        define function linkage/exportedness +    When the function is called, the arguments must be populated and the block must be executed.  .. crowbar:element:: FunctionSignature <- Type identifier '(' SignatureArguments? ')'                       SignatureArguments <- Type identifier (',' Type identifier)* ','? -     + +    Compile-time Behavior: +      A function signature specifies the return type, name, and arguments of a function. + +    Runtime Behavior: + +    A function signature has no runtime behavior. diff --git a/language/include.rst b/language/include.rst index cc2964a..4667a49 100644 --- a/language/include.rst +++ b/language/include.rst @@ -3,5 +3,10 @@ Including Headers  .. crowbar:element:: IncludeStatement <- 'include' string-literal ';' +    Compile-time Behavior: +      When encountering this statement at the beginning of a file, the compiler should interpret the string literal as a relative file path, look up the corresponding file in an implementation-defined way, and load the definitions from the given :crowbar:ref:`HeaderFile`. -    This statement has no runtime effect. + +    Runtime Behavior: + +    This statement has no runtime behavior. diff --git a/language/index.rst b/language/index.rst index 66492a9..e1e2b01 100644 --- a/language/index.rst +++ b/language/index.rst @@ -13,9 +13,10 @@ Syntax elements in this document are given in the form of `parsing expression gr  ..  toctree::      :maxdepth: 1 -     +      scanning      source-file      include      type-definition      functions +    statements/index diff --git a/language/scanning.rst b/language/scanning.rst index 3ed9bfe..a141b41 100644 --- a/language/scanning.rst +++ b/language/scanning.rst @@ -13,18 +13,18 @@ Scanning      keyword          One of the literal words ``bool``, ``break``, ``case``,          ``char``, ``const``, ``continue``, ``default``, ``do``, ``double``, -        ``else``, ``enum``, ``extern``, ``float``, ``for``, ``fragile``, +        ``else``, ``enum``, ``extern``, ``false``, ``float``, ``for``, ``fragile``,          ``function``, ``if``, :crowbar:ref:`include <IncludeStatement>`, ``int``, ``long``, ``opaque``, ``return``, -        ``short``, ``signed``, ``sizeof``, ``struct``, ``switch``, ``union``, +        ``short``, ``signed``, ``sizeof``, ``struct``, ``switch``, ``true``, ``union``,          ``unsigned``, ``void``, or ``while``. -     +      identifier          A nonempty sequence of characters blah blah blah          .. todo::              figure out https://www.unicode.org/reports/tr31/tr31-33.html -     +      constant          A numeric (or numeric-equivalent) value specified directly within the code.          May be a :term:`decimal constant`, a :term:`binary constant` , an :term:`octal constant`, @@ -50,12 +50,12 @@ Scanning      floating-point constant          A sequence of characters matching the regular expression ``[0-9_]+\.[0-9_]+([eE][+-]?[0-9_]+)?``. -         +          .. note::              Unlike in C and many other languages, ``6e3`` in Crowbar is not a valid floating-point constant.              The Crowbar-compatible spelling is ``6.0e3``. -         +          Denotes the numeric value of the given decimal number, optionally expressed in scientific notation.          That is, ``XeY`` denotes :math:`X * 10^Y`. @@ -63,12 +63,12 @@ Scanning          A sequence of characters matching the regular expression ``0(fx|FX)[0-9a-fA-F_]+\.[0-9a-fA-F_]+[pP][+-]?[0-9_]+``.          Denotes the numeric value of the given hexadecimal number expressed in binary scientific notation.          That is, ``XpY`` denotes :math:`X * 2^Y`. -     +      character constant          A pair of single quotes ``'`` surrounding either a single character or an :term:`escape sequence`.          The single character may not be a single quote or a backslash ``\``.          Denotes the Unicode scalar value for either the single surrounded character or the character denoted by the escape sequence. -     +      escape sequence          One of the following pairs of characters: @@ -79,7 +79,7 @@ Scanning          * ``\n``, denoting the line feed, or newline (U+000A)          * ``\t``, denoting the (horizontal) tab (U+0009)          * ``\0``, denoting a null character (U+0000) -         +          Or a sequence of characters matching one of the following regular expressions:          * ``\\x[0-9a-fA-F]{2}``, denoting the numeric value of the given two hexadecimal digits @@ -101,13 +101,13 @@ Scanning      whitespace          A nonempty sequence of characters that each has a Unicode general category of either Control (``Cc``) or Separator (``Z``).          Separates tokens. -     +      comment          Text that the compiler should ignore.          May be a :term:`line comment` or a :term:`block comment`. -     +      line comment          A sequence of characters beginning with the characters ``//`` (outside of a :term:`string literal` or :term:`comment`) and ending with a newline character U+000A. -     +      block comment          A sequence of characters beginning with the characters ``/*`` (outside of a :term:`string literal` or :term:`comment`) and ending with the characters ``*/``. diff --git a/language/source-file.rst b/language/source-file.rst index 2fc3ba0..162bb88 100644 --- a/language/source-file.rst +++ b/language/source-file.rst @@ -2,14 +2,14 @@ Source Files  ------------  .. crowbar:element:: HeaderFile <- IncludeStatement* HeaderFileElement+ -.. crowbar:element:: HeaderFileElement <- TypeDefinition / FunctionDeclaration / ConstantDefinition / VariableDeclaration +                     HeaderFileElement <- TypeDefinition / FunctionDeclaration / ConstantDefinition / VariableDeclaration      A Crowbar header file defines an API boundary, either at the surface of a library or between pieces of a library or application.      :crowbar:ref:`IncludeStatement`\ s can only appear at the beginning of the header file, and header files cannot define behavior directly.      Conventionally, a header file has a ``.hro`` file extension.  .. crowbar:element:: ImplementationFile <- IncludeStatement* ImplementationFileElement+ -.. crowbar:element:: ImplementationFileElement <- TypeDefinition / VariableDefinition / FunctionDefinition +                     ImplementationFileElement <- TypeDefinition / VariableDefinition / FunctionDefinition      A Crowbar implementation file defines the actual behavior of some piece of a library or application.      It can also define internal types, functions, and variables. diff --git a/language/statements/index.rst b/language/statements/index.rst new file mode 100644 index 0000000..38bfbb1 --- /dev/null +++ b/language/statements/index.rst @@ -0,0 +1,23 @@ +Statements +---------- + +.. crowbar:element:: Block <- '{' Statement* '}' + +    Compile-time Behavior: + +    A block is a possibly-empty sequence of statements surrounded by curly braces. +    Any declaration or definition within the block must not be visible outside of the block. + +    Runtime Behavior: + +    When a block is executed, each of the containing statements, in linear order, is executed. + +.. crowbar:element:: Statement <- VariableDefinition / StructureStatement / FlowControlStatement / AssignmentStatement / FragileStatement / ExpressionStatement + +    Crowbar has many different types of statement. + +..  toctree:: +    :maxdepth: 1 + +    variables +    structure diff --git a/language/statements/structure.rst b/language/statements/structure.rst new file mode 100644 index 0000000..9330bf6 --- /dev/null +++ b/language/statements/structure.rst @@ -0,0 +1,21 @@ +Structure Statements +^^^^^^^^^^^^^^^^^^^^ + +.. crowbar:element:: StructureStatement <- IfStatement / SwitchStatement / WhileStatement / DoWhileStatement / ForStatement + +    A structure statement creates some nonlinear control structure. +    There are several types of these structures. + +.. crowbar:element:: IfStatement <- 'if' '(' Expression ')' Block ('else' Block)? + +    An if statement allows some action to be performed only sometimes, based on the value of the expression. + +    Compile-time Behavior: + +    If the expression does not have type bool, the compiler must emit an error. + +    Runtime Behavior: + +    First, the expression is evaluated. +    If the expression evaluates to a ``bool`` value of ``true``, then the first block will be executed. +    If the expression evaluates to a ``bool`` value of ``false``, either the second block is executed or nothing is executed. diff --git a/language/statements/variables.rst b/language/statements/variables.rst new file mode 100644 index 0000000..6bc1a6f --- /dev/null +++ b/language/statements/variables.rst @@ -0,0 +1,24 @@ +Variables +^^^^^^^^^ + +.. crowbar:element:: VariableDeclaration <- Type identifier ';' + +    Compile-time Behavior: + +    A variable declaration specifies the type and name of a variable but not its initial value. +    This is only used in :crowbar:ref:`HeaderFile`\ s as part of API boundaries. + +    Runtime Behavior: + +    A variable declaration has no runtime behavior. + +.. crowbar:element:: VariableDefinition <- Type identifier '=' Expression ';' + +    Compile-time Behavior: + +    A variable definition specifies the type, name, and initial value of a variable. +    If the expression has a type which is not the type specified for the variable, an error must be emitted. + +    Runtime Behavior: + +    When a variable definition is executed, the expression is evaluated, and its result is made available with the given name. diff --git a/language/type-definition.rst b/language/type-definition.rst index b596d0a..9e3d7c4 100644 --- a/language/type-definition.rst +++ b/language/type-definition.rst @@ -5,6 +5,14 @@ Defining Types      Crowbar has three different kinds of user-defined types. +    Compile-time Behavior: + +    When a type is defined, the compiler must then allow that type to be used. + +    Runtime Behavior: + +    The definition of a type has no runtime behavior. +  .. crowbar:element:: StructDefinition <- NormalStructDefinition / OpaqueStructDefinition                       NormalStructDefinition <- 'struct' identifier '{' VariableDeclaration+ '}' @@ -25,7 +33,7 @@ Defining Types      An ``enum`` defines a type which can take one of several specified values.      .. todo:: -         +          define enum value assignment, type-related behavior  .. crowbar:element:: UnionDefinition <- RobustUnionDefinition / FragileUnionDefinition @@ -65,7 +73,7 @@ Defining Types                  case Whitespace: ;              }          } -     +      defines a ``union Token`` type, where the ``type`` field controls which of the other fields in the union is valid.      .. todo:: @@ -1,35 +1,35 @@ -@ECHO OFF
 -
 -pushd %~dp0
 -
 -REM Command file for Sphinx documentation
 -
 -if "%SPHINXBUILD%" == "" (
 -	set SPHINXBUILD=sphinx-build
 -)
 -set SOURCEDIR=.
 -set BUILDDIR=_build
 -
 -if "%1" == "" goto help
 -
 -%SPHINXBUILD% >NUL 2>NUL
 -if errorlevel 9009 (
 -	echo.
 -	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
 -	echo.installed, then set the SPHINXBUILD environment variable to point
 -	echo.to the full path of the 'sphinx-build' executable. Alternatively you
 -	echo.may add the Sphinx directory to PATH.
 -	echo.
 -	echo.If you don't have Sphinx installed, grab it from
 -	echo.http://sphinx-doc.org/
 -	exit /b 1
 -)
 -
 -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
 -goto end
 -
 -:help
 -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
 -
 -:end
 -popd
 +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( +	set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( +	echo. +	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx +	echo.installed, then set the SPHINXBUILD environment variable to point +	echo.to the full path of the 'sphinx-build' executable. Alternatively you +	echo.may add the Sphinx directory to PATH. +	echo. +	echo.If you don't have Sphinx installed, grab it from +	echo.http://sphinx-doc.org/ +	exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd @@ -58,7 +58,7 @@ Use after free  --------------  ``free(&x);`` will set ``x = NULL;`` -``owned`` and ``borrowed`` keywords  +``owned`` and ``borrowed`` keywords  Uninitialized variables  ======================= @@ -3,31 +3,15 @@  ### Statements  ```PEG -Block                   ← '{' Statement* '}' -     -Statement               ← VariableDefinition / -                          VariableDeclaration / -                          IfStatement / -                          SwitchStatement / -                          WhileStatement / -                          DoWhileStatement / -                          ForStatement / -                          FlowControlStatement / -                          AssignmentStatement / -                          ExpressionStatement -     -VariableDefinition      ← Type identifier '=' Expression ';' -VariableDeclaration     ← Type identifier ';' -      IfStatement             ← 'if' Expression Block 'else' Block /                            'if' Expression Block -     +  SwitchStatement         ← 'switch' Expression '{' SwitchCase+ '}'  SwitchCase              ← CaseSpecifier Block /                            'default' Block  CaseSpecifier           ← 'case' Expression ',' CaseSpecifier /                            'case' Expression ','? -     +  WhileStatement          ← 'while' Expression Block  DoWhileStatement        ← 'do' Block 'while' Expression ';'  ForStatement            ← 'for' VariableDefinition? ';' Expression ';' AssignmentStatementBody? Block @@ -70,7 +70,7 @@ Additions  Anti-Footguns  ------------- -*   C is generous with memory in ways that are unreliable by default.  +*   C is generous with memory in ways that are unreliable by default.      Crowbar adds :doc:`memory safety conventions <safety>` to make correctness the default behavior.  *   C's conventions for error handling are unreliable by default.      Crowbar adds :doc:`error propagation <errors>` to make correctness the default behavior.  |