Closed adam-mcdaniel closed 4 years ago
I'm not sure how I feel about implementing these constants in particular. I think more deliberation about which constants should be predefined is needed.
I would agree to be careful in defining constants. What should the requirements be before adding a constant? Maybe wait until programs are written where certain constants are required?
I think implementing all of C's predefined constants would be a good first step. Oak's include / conditional compiling architecture mirrors a lot of C's preprocessor directives, so it only makes sense that having C's predefined constants would be useful. I also think any possible information about the target is also necessary to add, like whether or not the Target supports floats, etc.
What do you think?
Id say taking some direction from C is a great start. But id be wary of implementing them all as it can get bloated quite fast.
I was also about to suggest that the Target gets some control about defining constants. Either by asking it questions like if it supports floats or giving it a hook to define constants. Maybe even both, im not sure how a language like C uses it. As some of those are language like features (TARGET
) but others might be very specific for the target language itself.
I think limiting the TARGET
constant to one character is a bad idea, as it'll limit the number of backends and force the use of nondescriptive characters for potential backends that share a letter (ex. Java and JavaScript)
The latest commit added the current_line()
and current_file()
operators. current_line()
can be used as a constant value anywhere, but current_file()
can only be used anywhere a literal string expression can.
These operators will make it easier for runtime error reporting.
user panic: error on line 23, in file "fileio.ok"
The newest commit also adds the import
compiler directive. This allows the compiler to include other files without redefinitions.
// main.ok
#[import("test1.ok")]
#[import("test2.ok")]
fn main() {
test1();
test2();
}
// test1.ok
fn test1() {
putstrln("Test 1");
}
// test2.ok
#[import("test1.ok")]
fn test2() {
test1(); // can use fns from test1
putstrln("Test 2");
}
The import flag isn't actually represented in TIR at all. It's exclusively dealt with in the parser.
#[import("test.ok")]
// Expands to the declaration
#[if(!is_defined("test.ok") {
#[define("test.ok", 1)]
#[include("test.ok")]
}]
This commit adds typed constants. Before, all constants were of type num
. Now, constants can be of type bool
, char
, or num
depending on the constant expression. With this change, constants do not need to be typecasted to be used as conditions, for example.
fn platform() -> &char {
return ON_WINDOWS? "windows"
: ON_MACOS? "macOS"
: ON_LINUX? "linux"
: "unknown";
}
TARGET
IS_STANDARD
ON_WINDOWS
ON_MACOS
ON_LINUX
ON_NIX
ON_NON_NIX
DATE_DAY
DATE_MONTH
DATE_YEAR
current_line()
current_file()