tov / dssl2 Goto Github PK
View Code? Open in Web Editor NEWA data structures student language, version 2
A data structures student language, version 2
The following program:
#lang dssl2
class Foo:
let length
def __init__(self):
pass
def len(self):
pass
def bar(self):
self.len = self.len + 1
Raises the error:
Racket v7.8/add-on/7.8/pkgs/dssl2/private/class-system.rkt:276:33: set!: cannot assign to def'd function or method
in: (set! «Foo».len (+ (struct-ref self len) 1))
This is clearly an error; the student wanted to set the length
field, but was trying to set the len
method instead.
But it would be nice to have an actual error for that, rather than an internal error.
@codeblock produces linked identifiers for #lang racket code, but for some reason it doesn’t for #lang dssl2.
which is not accepted by DSSL2. We should either change how strings are printed or accept that syntax as well.
Running raco test test/grader.rkt
or racket test/grader.rkt
fails, whereas running test/grader.rkt
inside DrRacket works. When running these tests in the terminal the output suggests that the code under test, which is supposed to attempt several DSSL2 tests, isn’t attempting any. This Racket 7.8 on is on MacOS Big Sur, so it might be a permission issue.
Standard library modules such as cons
and sbox_hash
should be documented.
The code range([1,2])
results in the error
range: contract violation
expected: num?
given: [1, 2]
in: the 1st argument of
the 3rd case of
(case->
(-> num? num? num? AnyC)
(-> num? num? AnyC)
(-> num? AnyC))
This is the correct contract for DSSL's range, but having an error message in terms of case->
and prefix ->
isn't ideal.
This program:
#lang dssl2
def fun():
helper()
def helper():
return 0
fun()
produces the error:
real-definition: undefined;
cannot use before initialization
without a useful source location.
real-definition
looks like some internal name leaking, but the name from the program would be better.
This code works:
defstruct Node(
prev: MaybeC(Node?),
data: MaybeC(X),
next: MaybeC(Node?))
But this code doesn't:
defstruct Node(
prev: Link,
data: MaybeC(X),
next: Link)
let Link = MaybeC(Node?)
It fails, saying that Link is undefined.
Compiling with raco make
makes it impossible to implement an interface in a different source file than where the interface is defined. In particular, objects of a class C
that implements an interface I
imported from another source file are not actually considered to implement interface I
by the I?
and I!
contracts.
Create a file lib.rkt
containing:
#lang dssl2
interface I: pass
Create a file client.rkt
containing:
#lang dssl2
import 'lib.rkt'
class C (I):
def __init__(self): pass
# This should succeed because C implements I, but it fails if you run
# `raco make` first. (It also fails in DrRacket.)
let o: I! = C()
Run client.rkt
:
$ racket client.rkt
$
Compile client.rkt
and run it again:
$ raco make client.rkt
$ racket client.rkt
o: broke its own contract;
class C does not implement interface I
in: I!
contract from: (definition o)
blaming: (definition o)
(assuming the contract is correct)
at: /Users/tov/Desktop/raco-make-weirdness/client.rkt:10.4
context...:
/Applications/Racket v7.4/collects/racket/contract/private/blame.rkt:347:0: raise-blame-error16
"/Users/tov/Desktop/raco-make-weirdness/client.rkt": [running body]
temp37_0
for-loop
run-module-instance!125
perform-require!78
$
Delete the compilation artifacts and run it again:
$ rm -R compiled
$ racket client.rkt
$
Consider this program:
#lang dssl2
class Foo[X]:
let _data
def __init__(self):
self.data = 10 # wrong var name
which produces the error:
bug-hw5.rkt:7:13: set!: unbound identifier
at: «Foo».data
in: (set! «Foo».data 10)
That error message isn't too bad (it clearly shows the field name at fault), but the fact that it it's terms of set!
isn't great.
FWIW, that happens only for class fields. Not for either local or global variables.
The very first DSSL2 code example in the docs (root insertion in a BST) refers to a number of undefined functions (e.g., empty?
, new_node
, fix_size
).
So it's not actually a working example that someone could just copy and run.
That's not great for the first example someone sees...
Especially confusing is the use of empty?
, which looks like a function that could plausibly be provided by the language. I just had a student assume (possibly based on that example) that DSSL2 provided an empty?
function, which it does not.
It should be easy to (un)comment multiple lines at once in DrRacket.
I've recently updated racket from 7.8.2 to 7.9.1 when updating my system.
Upon running any dssl2
script, I get:
standard-module-name-resolver: collection not found
for module path: dssl2/lang/reader
collection: "dssl2/lang"
in collection directories:
/home/marko/.racket/7.9/collects
/usr/share/racket/collects
... [161 additional linked and package directories]
I've tried running raco pkg install dssl2
, which threw:
Resolving "dssl2" via https://download.racket-lang.org/releases/7.9/catalog/
raco pkg install: cannot find package on catalogs
package: dssl2
curl https://download.racket-lang.org/releases/7.9/catalog/
gives a text/html
404.
This might be a racket
catalog issue, but I've skimmed their package catalog on GitHub (not sure if this is the right place), without any results. I've tried running:
grep -r -i dssl2 .
grep -r -i "jesse\.tov" .
grep -r -i northwestern .
where cwd
is the master
branch of the release catalog, commit adadb82, with no matches.
raco pkg install -t github tov/dssl2
and raco pkg install https://github.com/tov/dssl2.git
also don't work, being unhappy with the master
branch name change to main
. The error thrown is:
Querying Git references for dssl2 at git://github.com/tov/dssl2
git: could not find requested reference
reference: master
repo: tov/dssl2
context...:
/usr/share/racket/collects/net/git-checkout.rkt:359:0: select-commits
/usr/share/racket/collects/net/git-checkout.rkt:73:8
/usr/share/racket/collects/net/git-checkout.rkt:54:2: retry-loop
/usr/share/racket/collects/pkg/private/stage.rkt:59:2: lookup-normally
/usr/share/racket/collects/pkg/private/stage.rkt:107:0: stage-package/info
/usr/share/racket/collects/pkg/private/install.rkt:141:0: install-packages
/usr/share/racket/collects/pkg/private/install.rkt:925:4
/usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:555:3
/usr/share/racket/collects/racket/file.rkt:437:8
/usr/share/racket/collects/racket/file.rkt:426:0: call-with-file-lock
/usr/share/racket/collects/pkg/main.rkt:216:16
(submod "/usr/share/racket/collects/pkg/main.rkt" main): [running body]
"/usr/share/racket/collects/raco/raco.rkt": [running body]
"/usr/share/racket/collects/raco/main.rkt": [running body]
I did get things to work by manually cloning dssl2
manually and manually installing it with raco
, but, more importantly I checked whether DrRacket would install dssl2
well (as most people wouldn't probably know how to manually clone repos and would just follow the guide off the README
) and it didn't, throwing the same error.
I suggest leaving the master
branch name as a secondary branch until racket
fixes their master
-referring code.
Racket: 7.9.1
OS: Arch, latest
This program:
#lang dssl2
let x = [1,2,3]
x[[1,2]]
produces this error:
. . git/exp/plt/racket/share/pkgs/dssl2/private/syntax.rkt:418:7: «vec».__index_ref__: contract violation
expected: nat?
given: [1, 2]
in: the 1st argument of
(-> nat? AnyC)
contract from: «vec».__index_ref__
blaming: method caller
(assuming the contract is correct)
at: /Users/robby/tmp.rkt:3:0
which has a source location inside dssl2 instead of inside the dssl2 program.
Appears to require at least one of them to be defined in DSSL2 code (i.e, not built in).
#lang dssl2
class NotVec[K]:
def __init__(self):
pass
# this works
def foo(x: NotVec?):
pass
foo(NotVec[VecC[num?]]())
# this works too
def foo2(x: NotVec?[num?]):
pass
foo2(NotVec[num?]())
# this does not, contract violation
def foo3(x: NotVec?[VecC[num?]]):
pass
foo3(NotVec[VecC[num?]]())
# this also works, different higher-order contract
def bar (x: FunC[num?, num?]):
pass
bar(λ x: x)
We should be able to write:
def sum_vec(v: vec[int]):
let res = 0
for n in v: res += n
res
but they are read as "nan", "inf", and "-inf". This should be made to match.
Let's get rid of predicates like int?
and use the int
class instead. Examples:
def f(x: int) -> int:
…
if isinstance(y, int):
…
This is because parametric->/c
isn't nice about how it wraps its argument, I suppose. Is there a way to get the right name on it?
The tests for the grader fail when run from the command line but succeed
in DrRacket. Why?
The language does not appear to support inline struct literal construction syntax.
This statement does not work:
let customers = [
customer { name: 'Alice', bank_account: Account(1, 'savings', 10) },
customer { name: 'Bob', bank_account: Account(2, 'checking', 5) }
]
The following error is thrown:
hw1.rkt:163:8: Syntax error: unexpected token ‘customer’
context...:
/usr/share/racket/collects/syntax/readerr.rkt:6:2: raise-read-error
/usr/share/racket/pkgs/parser-tools-lib/parser-tools/yacc.rkt:347:16: parsing-loop
/usr/share/racket/collects/syntax/module-reader.rkt:186:17: body
/usr/share/racket/collects/syntax/module-reader.rkt:183:2: wrap-internal
lang:read-syntax
read-syntax
default-load-handler
standard-module-name-resolver
module-path-index-resolve
[repeats 1 more time]
module-declared?
However, this syntax works, throwing no errors:
let c1 = customer { name: 'Alice', bank_account: Account(1, 'savings', 10) }
let c2 = customer { name: 'Bob', bank_account: Account(2, 'checking', 5) }
let customers = [c1, c2]
Also, please observe that the following will throw an error:
let customers = [
{ name: 'Alice', bank_account: Account(1, 'savings', 10) },
{ name: 'Bob', bank_account: Account(2, 'checking', 5) }
]
That error is:
hw1.rkt:155:8: Syntax error: unexpected token ‘LBRACE’
context...:
/usr/share/racket/collects/syntax/readerr.rkt:6:2: raise-read-error
/usr/share/racket/pkgs/parser-tools-lib/parser-tools/yacc.rkt:347:16: parsing-loop
/usr/share/racket/collects/syntax/module-reader.rkt:186:17: body
/usr/share/racket/collects/syntax/module-reader.rkt:183:2: wrap-internal
lang:read-syntax
read-syntax
default-load-handler
standard-module-name-resolver
module-path-index-resolve
[repeats 1 more time]
module-declared?
This appears to indicate that inline struct literal construction does not work. Note that class construction is also employed in this example and it does not present any issues to the interpreter.
Perhaps it would be beneficial and would be a QOL upgrade to enable inline struct construction.
Additional Information
Arch Linux, latest
7.8
def sum(*args):
let res = 0
for a in args: res = res + a
return res
assert_eq sum(1, 2, 3, 4), 10
assert_eq sum(1, *[2, 3, 4]), 10
This program:
#lang dssl2
import array
let x = array()
x[0]
produces this internal error:
dssl-printer: format string did not match number of params
format string: 'Array index out of bounds: ~a >= ~a'
expected params: 0
actual params: 2
Thanks to Sonam Ford for the test case.
In this program:
#lang dssl2
class C:
let fd
def __init__(self):
self.fd == None
C()
the error message points inside the class system. Changing this code to:
(syntax/loc stx ...)
where the ellipses has what's currently on those lines (minus the #'
) seems to fix the issue.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.