aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2020-11-02 13:37:32 -0700
committerMelody Horn <melody@boringcactus.com>2020-11-02 13:37:32 -0700
commit8868b5fa2e8b9f40a31035c51519cce40e73f079 (patch)
tree4a91e7d5437f91a7f95358753097a99e2c84cf2e
parent83e23b6b449112f4a85d09c57e5601faa87856ca (diff)
downloadspec-8868b5fa2e8b9f40a31035c51519cce40e73f079.tar.gz
spec-8868b5fa2e8b9f40a31035c51519cce40e73f079.zip
define compile-time vs runtime behavior
-rw-r--r--.editorconfig1
-rw-r--r--_ext/crowbar_domain.py2
-rw-r--r--_ext/gemtext_builder.py30
-rw-r--r--index.rst2
-rw-r--r--language/functions.rst30
-rw-r--r--language/include.rst7
-rw-r--r--language/index.rst3
-rw-r--r--language/scanning.rst24
-rw-r--r--language/source-file.rst4
-rw-r--r--language/statements/index.rst23
-rw-r--r--language/statements/structure.rst21
-rw-r--r--language/statements/variables.rst24
-rw-r--r--language/type-definition.rst12
-rw-r--r--make.bat70
-rw-r--r--safety.rst2
-rw-r--r--syntax.md20
-rw-r--r--vs-c.rst2
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)
diff --git a/index.rst b/index.rst
index 92e9a4d..8155b3c 100644
--- a/index.rst
+++ b/index.rst
@@ -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::
diff --git a/make.bat b/make.bat
index 2119f51..922152e 100644
--- a/make.bat
+++ b/make.bat
@@ -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
diff --git a/safety.rst b/safety.rst
index 61cca97..6a73b85 100644
--- a/safety.rst
+++ b/safety.rst
@@ -58,7 +58,7 @@ Use after free
--------------
``free(&x);`` will set ``x = NULL;``
-``owned`` and ``borrowed`` keywords
+``owned`` and ``borrowed`` keywords
Uninitialized variables
=======================
diff --git a/syntax.md b/syntax.md
index e6ec9f1..b8e4554 100644
--- a/syntax.md
+++ b/syntax.md
@@ -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
diff --git a/vs-c.rst b/vs-c.rst
index 8317155..42f8a38 100644
--- a/vs-c.rst
+++ b/vs-c.rst
@@ -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.