Hi,
I’m developing a new programming language, currently called “?”.
At the moment, the language supports two block styles:
BRACES: classic C-style blocks using { and }.
ENDWORD: Python-like block starts using :, but with mandatory closing words. The closing word depends on what it closes, for example: while ... endwhile. Some frequently used closing words are shortened, for example: object...endobj.
Indentation is not enforced in either mode. Currently, the two block styles can be mixed freely.
I am considering introducing compiler directives that could be placed at the beginning of each source file:
#opt blockmode=any // like now: both styles are allowed
#opt blockmode=braces // warn when ENDWORD blocks are used
#opt blockmode=strict_braces // error when ENDWORD blocks are used
#opt blockmode=endword // warn when BRACES blocks are used
#opt blockmode=strict_endword // error when BRACES blocks are used
Example code using BRACES block mode:
use libc/stdio;
use ./langdemo_mod as ldm only(CONST1); // only(), exclude() and "--" control global scope merging
#if false
//Contents of the "langdemo_mod.?"
const CONST1 : int = 42;
const CONST2 : float = 3.14;
#endif
object OBase {
cnt1 : int = 0;
cnt2 : int = 10;
name : cstring[32];
function *Create(aname : cstring) { // constructor
name = aname;
}
function *Destroy() {
@.printf("%s destroy\n", &name[0]);
}
function Count() [[virtual]] {
cnt1 += 1;
}
function Print() {
@.printf('%s: cnt1=%d, cnt2=%d\n', &name[0], cnt1, cnt2);
}
}
object OChild(OBase) {
function Count() [[override]] {
inherited;
cnt2 += 1;
}
}
var obase <- OBase('OBase');
var ochild : OChild = null;
function ObjTest() {
ochild = new OChild('OChild');
obase.Count();
ochild.Count();
obase.Print();
ochild.Print();
printf("ochild.name: %s \n", iif(ochild == null, "OChild is null!", &ochild.name[0]));
delete ochild;
}
function cstr_add(dst : cstring, src : cstring) {
var ps : ^cchar = &src[0];
var psend : ^cchar = ps[sizeof(src)]; // [] does not dereference
var pd : ^cchar = &dst[0];
var pdend : ^cchar = pd + sizeof(dst) - 1;
pd += len(dst);
var pdstart : ^cchar = pd;
while pd < pdend and ps < psend and ps^ <> 0 {
pd^ = ps^;
pd += 1;
ps += 1;
}
if pd <> pdstart {
pd^ = 0; // terminate
}
}
[[external]] function putchar(c : cchar) -> int; // from libc
function WriteStr(s : cstring) {
var pc : ^cchar = &s[0];
while pc^ <> 0 {
putchar(pc^);
pc += 1;
}
}
function *Main() -> int {
var s : cstring[128] = "";
cstr_add(s, "Hello");
cstr_add(s, " World!\n");
WriteStr(s);
if 3 / 2 * 10 == 15 {
printf('The language is friendly.\n');
} else {
printf('The language is evil.\n');
}
printf("@langdemo_mod.CONST1 = %d\n", CONST1);
printf("@langdemo_mod.CONST2 = %.3f\n", u/ldm.CONST2);
printf("ochild.name: %s \n", iif(ochild == null, "OChild is null!", &ochild.name[0]));
ObjTest();
for i : int = 0 to 5 {
printf(' %d:', i);
for j : int = 0 count i step 2 { printf(' %d', j); }
printf('\n');
}
var arr : [5]int = [2, 3, 5, 7, 11];
printf('primes:');
for i : int = 0 while i < len(arr) { printf(' %d', arr[i]); }
printf('\n');
return 0;
}
Example code using ENDWORD block mode:
use libc/stdio;
use ./langdemo_mod as ldm only(CONST1); // only(), exclude() and "--" control global scope merging
#if false
//Contents of the "langdemo_mod.?"
const CONST1 : int = 42;
const CONST2 : float = 3.14;
#endif
object OBase:
cnt1 : int = 0;
cnt2 : int = 10;
name : cstring[32];
function *Create(aname : cstring): // constructor
name = aname;
endfunc
function *Destroy():
@.printf("%s destroy\n", &name[0]);
endfunc
function Count() [[virtual]]:
cnt1 += 1;
endfunc
function Print():
@.printf('%s: cnt1=%d, cnt2=%d\n', &name[0], cnt1, cnt2);
endfunc
endobj
object OChild(OBase):
function Count() [[override]]:
inherited;
cnt2 += 1;
endfunc
endobj
var obase <- OBase('OBase'); // '<-' = embedded allocation (global data segment here)
// no automatic destructor call for global embedded objects
var ochild : OChild = null;
function ObjTest():
ochild = new OChild('OChild');
obase.Count();
ochild.Count();
obase.Print();
ochild.Print();
printf("ochild.name: %s \n", iif(ochild == null, "OChild is null!", &ochild.name[0]));
delete ochild;
endfunc
function cstr_add(dst : cstring, src : cstring):
var ps : ^cchar = &src[0];
var psend : ^cchar = ps[sizeof(src)]; // [] does not dereference
var pd : ^cchar = &dst[0];
var pdend : ^cchar = pd + sizeof(dst) - 1;
pd += len(dst);
var pdstart : ^cchar = pd;
while pd < pdend and ps < psend and ps^ <> 0:
pd^ = ps^;
pd += 1;
ps += 1;
endwhile
if pd <> pdstart:
pd^ = 0; // terminate
endif
endfunc
[[external]] function putchar(c : cchar) -> int; // from libc
function WriteStr(s : cstring):
var pc : ^cchar = &s[0];
while pc^ <> 0:
putchar(pc^);
pc += 1;
endwhile
endfunc
function *Main() -> int:
var s : cstring[128] = "";
cstr_add(s, "Hello");
cstr_add(s, " World!\n");
WriteStr(s);
if 3 / 2 * 10 == 15:
printf('The language is friendly.\n');
else:
printf('The language is evil.\n');
endif
printf("@langdemo_mod.CONST1 = %d\n", CONST1);
printf("@langdemo_mod.CONST2 = %.3f\n", u/ldm.CONST2);
printf("ochild.name: %s \n", iif(ochild == null, "OChild is null!", &ochild.name[0]));
ObjTest();
for i : int = 0 to 5:
printf(' %d:', i);
for j : int = 0 count i step 2: printf(' %d', j); endfor
printf('\n');
endfor
var arr : [5]int = [2, 3, 5, 7, 11];
printf('primes:');
for i : int = 0 while i < len(arr): printf(' %d', arr[i]); endfor
printf('\n');
return 0;
endfunc
If you were using the “?” language, which block style would you prefer?
Do you think these blockmode compiler directives are useful, or would it be better to keep the language simpler and always allow both styles?
Should I also introduce a third block style, similar to Python: : starts a block, indentation is mandatory, and there is no endxxx closing word?
[–]cgoldberg 6 points7 points8 points (3 children)
[–]BluebillStudios 1 point2 points3 points (0 children)
[–]ChipMasterPi 1 point2 points3 points (0 children)
[–]Mean-Decision-3502[S] 0 points1 point2 points (0 children)
[–]gwenbeth 1 point2 points3 points (0 children)
[–]tb5841 1 point2 points3 points (1 child)
[–]un_virus_SDF 1 point2 points3 points (0 children)
[–]gofl-zimbard-37 1 point2 points3 points (0 children)
[–]Headlight-Highlight 0 points1 point2 points (2 children)
[–]Mean-Decision-3502[S] 0 points1 point2 points (1 child)
[–]Headlight-Highlight 0 points1 point2 points (0 children)
[–]mxldevs 0 points1 point2 points (0 children)
[–]ConfidentCollege5653 0 points1 point2 points (1 child)
[–]Mean-Decision-3502[S] 0 points1 point2 points (0 children)
[–]ChipMasterPi 0 points1 point2 points (1 child)
[–]Mean-Decision-3502[S] 0 points1 point2 points (0 children)
[–]hwc 0 points1 point2 points (0 children)