Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make language specification available as a PDF #7432

Merged
merged 3 commits into from Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 11 additions & 1 deletion .travis.yml
@@ -1,7 +1,8 @@
version: ~> 1.0 # needed for imports

import: scala/scala-dev:travis/default.yml

dist: bionic # for generating spec PDF; see #7432

language: scala

stages:
Expand Down Expand Up @@ -105,10 +106,19 @@ jobs:
- gem install bundler
- bundler --version
- bundle install
# cribbed from https://github.com/SebastiaanKlippert/go-wkhtmltopdf/blob/master/.travis.yml
- sudo apt-get update
- sudo apt-get install -y build-essential xorg xfonts-75dpi libpng16-16 libssl1.1
- wget --quiet "https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.bionic_amd64.deb"
- sudo dpkg -i "wkhtmltox_0.12.6-1.bionic_amd64.deb"
- rm "wkhtmltox_0.12.6-1.bionic_amd64.deb"
script:
- set -e
- (cd admin && ./init.sh)
- bundle exec jekyll build -s spec/ -d build/spec
- export JEKYLL_ENV=spec-pdf
- bundle exec jekyll build -s spec/ -d build/spec-pdf
- ./scripts/generate-spec-pdf.sh
after_success:
- ./scripts/travis-publish-spec.sh

Expand Down
24 changes: 24 additions & 0 deletions scripts/generate-spec-pdf.bat
@@ -0,0 +1,24 @@
@ECHO OFF
SETLOCAL EnableDelayedExpansion

REM NOTES:
REM "toc" -> treated just like another page, its location can be changed
REM "--window-status loaded" -> when window.status is set to "loaded", wkhtmltopdf knows js is loaded

SET THIS_SCRIPT_DIR=%~dp0
SET ROOT_DIR=%THIS_SCRIPT_DIR%..
SET SPEC_SRC_DIR=%ROOT_DIR%\spec
SET SPEC_BUILD_DIR=%ROOT_DIR%\build\spec

SET WKHTML_OPTS=--print-media-type --window-status loaded --footer-center [page] --javascript-delay 1000 --footer-font-name "Luxi Sans"
SET WKHTML_TOC=toc --xsl-style-sheet %SPEC_SRC_DIR%\spec-toc.xslt

SET HTML_FILES=
FOR /F "tokens=*" %%a IN ('dir %SPEC_BUILD_DIR%\*.html /B /O:N ^| findstr /v /i "index.*"') DO (
SET HTML_FILES=!HTML_FILES! %SPEC_BUILD_DIR%\%%a
)
ECHO Making Spec.pdf with HTML files:
ECHO %SPEC_BUILD_DIR%\index.html %HTML_FILES%

REM first goes index.html, then TOC, then rest
wkhtmltopdf %WKHTML_OPTS% %SPEC_BUILD_DIR%\index.html %WKHTML_TOC% %HTML_FILES% %SPEC_BUILD_DIR%\Spec.pdf
39 changes: 39 additions & 0 deletions scripts/generate-spec-pdf.sh
@@ -0,0 +1,39 @@
#!/usr/bin/env bash

set -e
set -v

# NOTES:
# "toc" -> treated just like another page, its location can be changed
# "--window-status loaded" -> when window.status is set to "loaded", wkhtmltopdf knows js is loaded

THIS_SCRIPT_DIR=$(dirname $0)
ROOT_DIR=$THIS_SCRIPT_DIR/..
SPEC_SRC_DIR=$ROOT_DIR/spec
SPEC_BUILD_DIR=$ROOT_DIR/build/spec
SPEC_PDF_BUILD_DIR=$ROOT_DIR/build/spec-pdf
PDF=$SPEC_BUILD_DIR/spec.pdf

mkdir -p $SPEC_PDF_BUILD_DIR


WKHTML_OPTS='--print-media-type --window-status loaded --javascript-delay 1000 --load-error-handling ignore --enable-local-file-access --footer-center [page] --footer-font-name "Luxi Sans"'
WKHTML_TOC="toc --xsl-style-sheet $SPEC_SRC_DIR/spec-toc.xslt"

# exclude index.html, prepend SPEC_PDF_BUILD_DIR path
HTML_FILES=$(ls $SPEC_PDF_BUILD_DIR | grep -vx 'index.html' | grep '\.html$' | while read line; do echo "$SPEC_PDF_BUILD_DIR/$line"; done)
echo "Making spec.pdf with HTML files: "
echo $SPEC_PDF_BUILD_DIR/index.html $HTML_FILES
# first goes index.html, then TOC, then rest
rm -f $PDF
wkhtmltopdf $WKHTML_OPTS $SPEC_PDF_BUILD_DIR/index.html $WKHTML_TOC $HTML_FILES $PDF || true
# the '|| true' thing is because we get:
# Error: Failed to load http:/, with network status code 3 and http status code 0 - Host not found
# Warning: Failed loading page http: (ignored)
# as long we have `--load-error-handling ignore` we still get a PDF, but we also get a nonzero exit code
# fail if we didn't get a PDF file out
if [ ! -f $PDF ] ; then exit 1 ; fi
48 changes: 24 additions & 24 deletions spec/01-lexical-syntax.md
Expand Up @@ -93,8 +93,8 @@ Some examples of constant identifiers are
> ⅰ_ⅲ Ⅰ_Ⅲ ↁelerious ǃqhàà ʹthatsaletter
> ```
The ‘\$’ character is reserved for compiler-synthesized identifiers.
User programs should not define identifiers that contain ‘\$’ characters.
The ‘$’ character is reserved for compiler-synthesized identifiers.
User programs should not define identifiers that contain ‘$’ characters.

The following names are reserved words instead of being members of the
syntactic class `id` of lexical identifiers.
Expand All @@ -111,7 +111,7 @@ val var while with yield
_ : = => <- <: <% >: # @
```

The Unicode operators `\u21D2`$\Rightarrow$’ and `\u2190`$\leftarrow$’, which have the ASCII
The Unicode operators `\u21D2`´\Rightarrow´’ and `\u2190`´\leftarrow´’, which have the ASCII
equivalents `=>` and `<-`, are also reserved.

> Here are examples of identifiers:
Expand Down Expand Up @@ -357,9 +357,9 @@ is _pt_. The numeric ranges given by these types are:

| | |
|----------------|--------------------------|
|`Byte` | $-2\^7$ to $2\^7-1$ |
|`Short` | $-2\^{15}$ to $2\^{15}-1$|
|`Char` | $0$ to $2\^{16}-1$ |
|`Byte` | ´-2\^7´ to ´2\^7-1´ |
|`Short` | ´-2\^{15}´ to ´2\^{15}-1´|
|`Char` | ´0´ to ´2\^{16}-1´ |

The digits of a numeric literal may be separated by
arbitrarily many underscores for purposes of legibility.
Expand Down Expand Up @@ -503,11 +503,11 @@ not processed, except for Unicode escapes.
#### Interpolated string

```ebnf
interpolatedString ::= alphaid ‘"’ {printableChar \ (‘"’ | ‘\$’) | escape} ‘"’
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘\$’) | escape} {‘"’} ‘"""’
escape ::= ‘\$\$’
| ‘\$’ id
| ‘\$’ BlockExpr
interpolatedString ::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’
| alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’
escape ::= ‘$$’
| ‘$’ id
| ‘$’ BlockExpr
alphaid ::= upper idrest
| varid
Expand All @@ -522,24 +522,24 @@ or multi-line (triple quote).
Inside a interpolated string none of the usual escape characters are interpreted
(except for unicode escapes) no matter whether the string literal is normal
(enclosed in single quotes) or multi-line (enclosed in triple quotes).
Instead, there is are two new forms of dollar sign escape.
The most general form encloses an expression in \${ and }, i.e. \${expr}.
The expression enclosed in the braces that follow the leading \$ character is of
Instead, there are two new forms of dollar sign escape.
The most general form encloses an expression in `${` and `}`, i.e. `${expr}`.
The expression enclosed in the braces that follow the leading `$` character is of
syntactical category BlockExpr. Hence, it can contain multiple statements,
and newlines are significant. Single ‘\$’-signs are not permitted in isolation
in a interpolated string. A single ‘\$’-sign can still be obtained by doubling the ‘\$
character: ‘\$\$’.
and newlines are significant. Single ‘$’-signs are not permitted in isolation
in a interpolated string. A single ‘$’-sign can still be obtained by doubling the ‘$’
character: ‘$$’.

The simpler form consists of a ‘\$’-sign followed by an identifier starting with
The simpler form consists of a ‘$’-sign followed by an identifier starting with
a letter and followed only by letters, digits, and underscore characters,
e.g \$id. The simpler form is expanded by putting braces around the identifier,
e.g \$id is equivalent to \${id}. In the following, unless we explicitly state otherwise,
e.g `$id`. The simpler form is expanded by putting braces around the identifier,
e.g `$id` is equivalent to `${id}`. In the following, unless we explicitly state otherwise,
we assume that this expansion has already been performed.

The expanded expression is type checked normally. Usually, StringContext will resolve to
The expanded expression is type checked normally. Usually, `StringContext` will resolve to
the default implementation in the scala package,
but it could also be user-defined. Note that new interpolators can also be added through
implicit conversion of the built-in scala.StringContext.
implicit conversion of the built-in `scala.StringContext`.

One could write an extension
```scala
Expand Down Expand Up @@ -576,8 +576,8 @@ symbolLiteral ::= ‘'’ plainid
```

A symbol literal `'x` is a shorthand for the expression `scala.Symbol("x")` and
is of the [literal type](03-types.html#literal-types) `'x`. `Symbol` is a [case
class](05-classes-and-objects.html#case-classes), which is defined as follows.
is of the [literal type](03-types.html#literal-types) `'x`.
`Symbol` is a [case class](05-classes-and-objects.html#case-classes), which is defined as follows.

```scala
package scala
Expand Down
40 changes: 20 additions & 20 deletions spec/02-identifiers-names-and-scopes.md
Expand Up @@ -48,24 +48,24 @@ locally {
}
```

A reference to an unqualified (type- or term-) identifier $x$ is bound
A reference to an unqualified (type- or term-) identifier ´x´ is bound
by the unique binding, which

- defines an entity with name $x$ in the same namespace as the identifier, and
- shadows all other bindings that define entities with name $x$ in that
- defines an entity with name ´x´ in the same namespace as the identifier, and
- shadows all other bindings that define entities with name ´x´ in that
namespace.

It is an error if no such binding exists. If $x$ is bound by an
import clause, then the simple name $x$ is taken to be equivalent to
the qualified name to which $x$ is mapped by the import clause. If $x$
is bound by a definition or declaration, then $x$ refers to the entity
introduced by that binding. In that case, the type of $x$ is the type
It is an error if no such binding exists. If ´x´ is bound by an
import clause, then the simple name ´x´ is taken to be equivalent to
the qualified name to which ´x´ is mapped by the import clause. If ´x´
is bound by a definition or declaration, then ´x´ refers to the entity
introduced by that binding. In that case, the type of ´x´ is the type
of the referenced entity.

A reference to a qualified (type- or term-) identifier $e.x$ refers to
the member of the type $T$ of $e$ which has the name $x$ in the same
namespace as the identifier. It is an error if $T$ is not a [value type](03-types.html#value-types).
The type of $e.x$ is the member type of the referenced entity in $T$.
A reference to a qualified (type- or term-) identifier ´e.x´ refers to
the member of the type ´T´ of ´e´ which has the name ´x´ in the same
namespace as the identifier. It is an error if ´T´ is not a [value type](03-types.html#value-types).
The type of ´e.x´ is the member type of the referenced entity in ´T´.

Binding precedence implies that the way source is bundled in files affects name resolution.
In particular, imported names have higher precedence than names, defined in other files,
Expand Down Expand Up @@ -160,24 +160,24 @@ precedences between them.
package p { // `X' bound by package clause
import Console._ // `println' bound by wildcard import
object Y {
println(s"L4: \$X") // `X' refers to `p.X' here
println(s"L4: $X") // `X' refers to `p.X' here
locally {
import q._ // `X' bound by wildcard import
println(s"L7: \$X") // `X' refers to `q.X' here
println(s"L7: $X") // `X' refers to `q.X' here
import X._ // `x' and `y' bound by wildcard import
println(s"L9: \$x") // `x' refers to `q.X.x' here
println(s"L9: $x") // `x' refers to `q.X.x' here
locally {
val x = 3 // `x' bound by local definition
println(s"L12: \$x") // `x' refers to constant `3' here
println(s"L12: $x") // `x' refers to constant `3' here
locally {
import q.X._ // `x' and `y' bound by wildcard import
// println(s"L15: \$x") // reference to `x' is ambiguous here
// println(s"L15: $x") // reference to `x' is ambiguous here
import X.y // `y' bound by explicit import
println(s"L17: \$y") // `y' refers to `q.X.y' here
println(s"L17: $y") // `y' refers to `q.X.y' here
locally {
val x = "abc" // `x' bound by local definition
import p.X._ // `x' and `y' bound by wildcard import
// println(s"L21: \$y") // reference to `y' is ambiguous here
println(s"L22: \$x") // `x' refers to string "abc" here
// println(s"L21: $y") // reference to `y' is ambiguous here
println(s"L22: $x") // `x' refers to string "abc" here
}}}}}}
```