Based on practical experience and discussions with other developers, this release officially adds the following new elements to the language.
Exception Handling
See here for a discussion and derivation.
See here for the specs.
Here is an example as implemented in this release:
module ExceptionExample
type Exception = record end
proc Print(in str: array of char)
var e: pointer to Exception
begin
println(str)
new(e)
raise(e)
println("this is not printed")
end Print
var res: pointer to anyrec
begin
pcall(res, Print, "Hello World")
case res of
| Exception: println("got Exception")
| anyrec: println("got anyrec")
| nil: println("no exception")
else
println("unknown exception")
// could call raise(res) here to propagate the exception
end
end ExceptionExample
Source code directives and conditional compilation
Oberon+ uses a syntax as suggested in the Oakwood guidelines.
See here for the specs.
Here is an example as implemented in this release:
<* AAA+ *>
<* BBB- *>
<* if AAA then *>
println("compiled for AAA")
<* elsif BBB & ~CCC then *>
println("compiled for BBB & ~CCC")
<* else *>
println("something else")
<* end *>
Variable length arrays (VLA)
In contrast to array pointers allocated with new(), variable length arrays (VLA) can be allocated on the stack instead of the heap, which makes them attractive to low-resource embedded applications where dynamic memory allocation is not feasible.
Here is an example as implemented in this release:
module VlaExample
proc Test(n, m: integer)
var i,j: integer; a: array var n, m of integer
begin
for i := 0 to n -1 do
for j := 0 to m-1 do
a[i,j] := i*j*2
end
end
println(a[2,3])
end Test
begin
Test(4,5)
end VlaExample
Non-local access
Oberon+ now also supports access to outer parameters and local variables from nested procedures (non-local access), as it was available in original Oberon and Oberon-2, but removed in Oberon-07.
Previous versions of Oberon+ followed Oberon-07 and didn’t support this feature, mostly because the "classic" implementation by "static links" doesn’t fit CIL/ECMA-335 or C99 backends; this version of Oberon+ supports an implementation based on hidden var parameters, which is feasible with the mentioned backends.
With this addition Oberon+ is now fully backwards compatible, i.e. each valid Oberon, Oberon-2 or Oberon-07 program is also a valid Oberon+ program.
Here is an example as implemented in this release:
module NlaExample
proc Outer()
var a,b,c: integer
proc Mid1( i: integer )
var d: integer
proc Inner( i: integer )
begin
a := a + i; d := i
Mid2(11)
end Inner
begin
b := b + i
Inner(12)
end Mid1
proc Mid2( i: integer )
begin
c := c + i
end Mid2
begin
a := 0; b := 0; c := 0
Mid1( 13 ) // calls Inner -> Mid2
Mid2( 14 )
println(a) // 12
println(b) // 13
println(c) // 11 + 14 = 25
end Outer
begin
Outer
end NlaExample
Precompiled versions
Here are the pre-compiled versions of the IDE (download, unpack/mount and run, no installation requried):
http://software.rochus-keller.ch/OberonIDE_win32.zip
http://software.rochus-keller.ch/OberonIDE_win64.zip
http://software.rochus-keller.ch/OberonIDE_macOS_x64.dmg
http://software.rochus-keller.ch/OberonIDE_linux_i386.tar.gz
http://software.rochus-keller.ch/OberonIDE_linux_x86_64.tar.gz
See also https://github.com/rochus-keller/Oberon/blob/master/README.md and http://oberon-lang.ch/.