Cleanup readme a little
Ok I'm a little done rn
Ok that was easy to sort out
A cursed modula-2 compiler.
It's modula 2, with a different syntax. Because modula-2 is surprisingly good, and the syntax and naming is just tedious. So the goal is to be exactly Modula-2 in terms of semantics, even the bits I don't particularly care for, with a syntax that is a little less bleh. (Well, I might leave out some of the multiprocessing bits and such.) I'm going to play around with various syntax ideas that have been bouncing around in my head anyway to see how they work in practice. I expect the result to be the most success-immune language of all time.
Name: because it's modulo 2! But lispy! HAH. Thanks, MBones.
Install Dotnet Core on your machine per instructions from https://fsharp.org/ . For Debian this is at https://docs.microsoft.com/en-us/dotnet/core/install/linux-debian. Dotnet Core should come with F# itself.
Then you should be able to just do:
dotnet build
dotnet run programs/fib.m2
Other useful commands:
dotnet test
dotnet clean
Probably doesn't work.
The syntax is more or less done, which is the fun part anyway, I am just like halfway through the parser.
Let's rewrite some stuff from the book to play with the ideas. Examples from chapter 6.2 of the book Programming In Modula-2 (4th ed).
MODULE Oscillation;
FROM InOut IMPORT ReadInt, WriteString, WriteLn;
FROM RealinOut IMPORT ReadReal, WriteReal;
FROM MathLib0 IMPORT exp, cos;
CONST dx = 0.19634953; (*pi/16*)
VAR i, n: INTEGER;
x, y, r: REAL;
BEGIN
WriteString(" n = "); Readlnt(n);
WriteString(" r = "); ReadReal(r); WriteLn;
i := 0; x := 0.0;
REPEAT x := x + dx; i := i+1;
Y := exp ( -r*x) * cos (x);
WriteReal(x, 15); WriteReal(y, 15); WriteLn
UNTIL i >= n
END Oscillation.
mod Oscillation
use InOut.ReadInt, WriteString, WriteLn
use RealinOut.ReadReal, WriteReal
use MathLib0.exp, cos
consts
dx = 0.19634953 ; pi/16
vars
; Var initialization semantically happens at the beginning of
; the `do` block? That might be more rewriting than I want.
i: int = 0
n: int = 0
x: float = 0.0
y: float = 0.0
r: float = 0.0
do
(WriteString " n = ") (ReadInt n)
(WriteString " r = ") (ReadReal r) (WriteLn)
repeat
x <- (+ x dx)
i <- (+ i 1)
y <- (* (exp (* (- r) x)) (cos x))
(WriteReal x 15) (WriteReal y 15) (WriteLn)
until (>= i n)
Thoughts: +=
operator? <-
or =
for assignment? =
or ==
for
equals? repeat ... until
loop becomes do ... while
, inverting the
sense of the test? do ... end
block syntax change?
We are NOT changing:
Let's iterate slightly
MODULE Power;
FROM InOut IMPORT Readlnt. WriteString, WriteLn;
FROM RealinOut IMPORT ReadReal, Done, WriteReal;
VAR i: INTEGER; x, z: REAL;
BEGIN
WriteString( "x = "); ReadReal (x);
WHILE Done DO
WriteString(" t i = "); ReadInt(i);
z := 1.0;
WHILE i > 0 DO
(* z * x^i = x0^i0 *)
IF ODD(i) THEN z := z*x END;
x := X*X; i := i DIV 2
END;
WriteReal(z,16); WriteLn;
WriteString("x = "); ReadReal(x)
END;
WriteLn
END Power.
mod Power
use InOut.ReadInt, WriteString, WriteLn
use RealinOut.ReadReal, Done, WriteReal
vars
i: int = 0
x, z: float = 0.0
do
(WriteString "x = ") (ReadReal x)
while (Done)
(WriteString " ^ i = ") (ReadInt)
z <- 0.0
while (> i 0)
; z * x^i = x0^i0
if (odd i) z <- z * x end
x <- x * x
i <- (div i 2)
end
(WriteReal z 16) (WriteLn)
(WriteString "x = ") (ReadReal x)
end
(WriteLn)
Thoughts:
mod Name ... is ...
//
instead of div
?From chapter 14 of the Book:
MODULE Permute;
FROM InOut IMPORT Read, Write, WriteLn;
VAR n: INTEGER; ch: CHAR;
a: ARRAY [1 .. 20] OF CHAR;
PROCEDURE output;
VAR i: INTEGER;
BEGIN
FOR i := 1 TO n DO Write(a[I]) END;
WrlteLn
END output;
PROCEDURE permute(k: INTEGER);
VAR i: INTEGER; t: CHAR;
BEGIN
IF k = 1 THEN output
ELSE permute(k-1);
FOR i := 1 TO k-1 DO
t := a [i] ; a [i] := a [k] ; a [ k] := t;
permute(k-1) ;
t := a (i]; a (i] := a [k]; a [k] := t
END
END
END permute;
BEGIN Write(")"); n := 0; Read(ch);
WHILE ch > " " DO
n := n+1; a[n1 := ch; Write(ch); Read(ch)
END;
WriteLn; permute(n)
END Permute.
mod Permute
use InOut.Read, Write, WriteLn
vars
n: int = 0
ch: char = '\0'
a: char[1..20] = TODO
fn output(a: char[])
vars i: int = 0
for i = 1 to n do
(Write a[i])
end
(WriteLn)
end
fn swap(a: char[], i: int, k: int)
vars tmp: char = 0
tmp <- a[i]
a[i] <- a[k]
a[k] <- tmp
end
fn permute(k: int)
vars i: int = 0
if (= k 1)
(output)
else
(permute (- k 1))
for i = 1 to (- k 1) do
(swap a i k)
(permute (- k 1))
(swap a i k)
end
end
end
do
(write "Enter chars to permute, end with space. >")
(read ch)
while (/= ch " ")
n <-+ 1
a[n] <- ch
(Read ch)
end
(WriteLn)
(permute n)
Hm, can we avoid needing to declare our for loop vars explicitly? Yeah you know what I heckin' think so.
Downside of <-
for assignment is that <-+
and <--
and <-*
and
such look weird. <+
maybe? Oops that would make minus <-
so that
doesn't work. Idk, try them out and see how they feel; it's a little
cute.
Feedback: fn (swap a:char[] i:int k:int)
instead of fn swap(...)
makes declarations more consistent with calls. On a line with a
function call you can drop the first and last parens and still be
unambiguous. Also using sexprs for expressions alone apparently triggers
a bigger flame war than using them for your whole language. People,
amirite?
mod Fib
; Playin' with import syntax. I like the rust approach 'cause
; you don't need to reorder keywords to change `import Foo` to
; `from Foo import A, B, C`
use InOut.ReadInt, WriteInt, Write, WriteLn
; Maybe something like:
; use InOut.(ReadInt, WriteInt, Write, WriteLn)
; ...nah, I'll give the parens a miss.
vars
n: int = 0
; I do like the `(fib i: int)` fn decl syntax for this.
; I could honestly remove the `fn` but let's keep a
; *little* tribute to the decl-heavy style.
;
; What do I do for return types? -> for now I suppose.
fn (fib i: int) -> int
if (<= i 2)
1
else
(+ (fib (- i 1)) (fib (- i 2)))
end
end
do
(Write "Enter number to calculate the fib for >")
(ReadInt n)
n <- (fib n)
(WriteInt n)
(WriteLn)
What should the backend be? Really I was only actually interested in a new syntax to see what it looks like. Options to consider:
Obfusticated Modula-2 (more work, but funnier) -- Very tempting actually. Stuff everything into one module, rename everything to lI1ll1l, turn all math into bitsets operations... Oh, there's a whole list: https://tigress.wtf/transformations.html
Rejected options:
Apache-2.0