forked from ooc-lang/the-ooc-language
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
155 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,147 +1,156 @@ | ||
Version blocks | ||
============== | ||
|
||
Syntax | ||
------ | ||
|
||
Version blocks use the following syntax: | ||
|
||
version (<version expression>) { | ||
<body> | ||
} | ||
|
||
Where <version expression> can be any of: | ||
|
||
<version name> | ||
!<version expression> | ||
<version expression> && <version expression> | ||
<version expression> || <version expression> | ||
|
||
Semantics | ||
--------- | ||
|
||
Version blocks aren't if-else blocks - they aren't evaluated at runtime. | ||
In rock, version blocks aren't evaluated at ooc-compile-time either. | ||
They're evaluated at C compile time. Which means the C code generated by rock | ||
should be the same on any platform. | ||
|
||
Practically, in rock, version blocks are an abstraction for #ifdef / #endif blocks. | ||
The syntax makes it harder to forget to close a version block than an #ifdef / #endif block, | ||
and a few handy aliases (listed below) for commonly used version names are standard, so that developers | ||
don't have to remember the convoluted corresponding C defines. | ||
|
||
For other compilers not based on the C language, version block handling may happen at any | ||
stage of the compilation (if any), as long as the version expressions are correctly evaluated | ||
and have the correct meaning (for example, a 'windows' version block should be ignored on OSX) | ||
|
||
Built-in version names | ||
---------------------- | ||
|
||
C defines are included here for completeness, but are only relevant for people who want | ||
to implement ooc on top of C. | ||
|
||
|Name |corresponding C define | | ||
|:-----:|:---------------------:| | ||
|windows|__WIN32__ || __WIN64__ | | ||
|linux |__linux__ | | ||
|solaris|__sun | | ||
|unix |__unix__ | | ||
|beos |__BEOS__ | | ||
|haiku |__HAIKU__ | | ||
|apple |__APPLE__ | | ||
|gnuc |__GNUC__ | | ||
|i386 |__i386__ | | ||
|x86 |__X86__ | | ||
|x86_64 |__x86_64__ | | ||
|ppc |__ppc__ | | ||
|ppc64 |__ppc64__ | | ||
|64 |__x86_64__ || __ppc64__| | ||
|gc |__OOC_USE_GC__ | | ||
|
||
Custom version names | ||
-------------------- | ||
|
||
Most of the standard version names above depend on your building environment, and the 'gc' name depends | ||
on the compiler setting -gc=[off,static,dynamic]. | ||
|
||
Custom version names can be used, and turned on/off with the -D and -U compiler flags, for example: | ||
|
||
version(debug) { | ||
"[%d] Saving database %s" println(timestamp(), db name) | ||
} | ||
db save() | ||
|
||
The code inside the version(debug) block will be compiled if -Ddebug is used. | ||
|
||
Semantics continued | ||
------------------- | ||
|
||
Version blocks can be used in function bodies, to make certain parts of the code OS-specific, or | ||
they can be used at the mdule-level to make functions or types OS-specific. | ||
|
||
If different types are defined in different version blocks, make sure they expose the same interface. | ||
It's not necessary for them to have the exact same class layout, but they should at least have all the | ||
methods/fields that are used in every OS. | ||
|
||
Examples | ||
-------- | ||
|
||
version(windows) { | ||
"Hi, Bill!" println() | ||
} | ||
version(apple) { | ||
"Hi, Steve!" println() | ||
} | ||
version(linux) { | ||
"Hi, Linus!" println() | ||
} | ||
version(!windows && !apple && !linux) { | ||
"Who are you, and what did you do to my OS?" | ||
} | ||
|
||
See also io/File and os/Time in the SDK for real-world examples of heavily versioned code. | ||
|
||
Pattern for OS-specific classes | ||
------------------------------- | ||
|
||
In ooc, 'new' isn't a keyword but a static method. As a result, you can define new yourself. | ||
This allows an interesting pattern for OS-specific classes in ooc: | ||
|
||
// io/File | ||
import io/[FileUnix, FileWin32] | ||
|
||
File: class { | ||
path: String | ||
|
||
new: static func (.path) -> This { | ||
version(windows) { return FileWin32 new(path) } | ||
version(unix) { return FileUnix new(path) } | ||
Exception new(This, "Unsupported platform") throw() | ||
} | ||
// abstract methods | ||
} | ||
|
||
// io/FileUnix | ||
FileUnix: class extends File { | ||
init: func (=path) {} | ||
// implement abstract methods for unix | ||
} | ||
|
||
// io/FileWin32 | ||
FileWin32: class extends File { | ||
init: func (=path) {} | ||
// implement abstract methods for Win32 | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Version blocks | ||
============== | ||
|
||
Syntax | ||
------ | ||
|
||
Version blocks use the following syntax: | ||
|
||
version (<version expression>) { | ||
<body> | ||
} else { | ||
<alternative body> | ||
} | ||
|
||
Where <version expression> can be any of: | ||
|
||
<version name> | ||
!<version expression> | ||
<version expression> && <version expression> | ||
<version expression> || <version expression> | ||
|
||
Semantics | ||
--------- | ||
|
||
Version blocks aren't if-else blocks - they aren't evaluated at runtime. | ||
In rock, version blocks aren't evaluated at ooc-compile-time either. | ||
They're evaluated at C compile time. Which means the C code generated by rock | ||
should be the same on any platform. | ||
|
||
Practically, in rock, version blocks are an abstraction for #ifdef / #endif blocks. | ||
The syntax makes it harder to forget to close a version block than an #ifdef / #endif block, | ||
and a few handy aliases (listed below) for commonly used version names are standard, so that developers | ||
don't have to remember the convoluted corresponding C defines. | ||
|
||
For other compilers not based on the C language, version block handling may happen at any | ||
stage of the compilation (if any), as long as the version expressions are correctly evaluated | ||
and have the correct meaning (for example, a 'windows' version block should be ignored on OSX) | ||
|
||
Built-in version names | ||
---------------------- | ||
|
||
C defines are included here for completeness, but are only relevant for people who want | ||
to implement ooc on top of C. | ||
|
||
|Name |corresponding C define | | ||
|:-----:|:---------------------:| | ||
|windows|__WIN32__ || __WIN64__ | | ||
|linux |__linux__ | | ||
|solaris|__sun | | ||
|unix |__unix__ | | ||
|beos |__BEOS__ | | ||
|haiku |__HAIKU__ | | ||
|apple |__APPLE__ | | ||
|gnuc |__GNUC__ | | ||
|i386 |__i386__ | | ||
|x86 |__X86__ | | ||
|x86_64 |__x86_64__ | | ||
|ppc |__ppc__ | | ||
|ppc64 |__ppc64__ | | ||
|64 |__x86_64__ || __ppc64__| | ||
|gc |__OOC_USE_GC__ | | ||
|
||
Custom version names | ||
-------------------- | ||
|
||
Most of the standard version names above depend on your building environment, and the 'gc' name depends | ||
on the compiler setting -gc=[off,static,dynamic]. | ||
|
||
Custom version names can be used, and turned on/off with the -D and -U compiler flags, for example: | ||
|
||
version(debug) { | ||
"[%d] Saving database %s" println(timestamp(), db name) | ||
} | ||
db save() | ||
|
||
The code inside the version(debug) block will be compiled if -Ddebug is used. | ||
|
||
Semantics continued | ||
------------------- | ||
|
||
Version blocks can be used in function bodies, to make certain parts of the code OS-specific, or | ||
they can be used at the mdule-level to make functions or types OS-specific. | ||
|
||
If different types are defined in different version blocks, make sure they expose the same interface. | ||
It's not necessary for them to have the exact same class layout, but they should at least have all the | ||
methods/fields that are used in every OS. | ||
|
||
Examples | ||
-------- | ||
|
||
version(windows) { | ||
"Hi, Bill!" println() | ||
} | ||
version(apple) { | ||
"Hi, Steve!" println() | ||
} | ||
version(linux) { | ||
"Hi, Linus!" println() | ||
} | ||
version(!windows && !apple && !linux) { | ||
"Who are you, and what did you do to my OS?" | ||
} | ||
|
||
|
||
version(apple) { | ||
"Nice Hardware!" println() | ||
} else { | ||
"So you like your computer made of plastic then!" println() | ||
} | ||
|
||
See also io/File and os/Time in the SDK for real-world examples of heavily versioned code. | ||
|
||
Pattern for OS-specific classes | ||
------------------------------- | ||
|
||
In ooc, 'new' isn't a keyword but a static method. As a result, you can define new yourself. | ||
This allows an interesting pattern for OS-specific classes in ooc: | ||
|
||
// io/File | ||
import io/[FileUnix, FileWin32] | ||
|
||
File: class { | ||
path: String | ||
|
||
new: static func (.path) -> This { | ||
version(windows) { return FileWin32 new(path) } | ||
version(unix) { return FileUnix new(path) } | ||
Exception new(This, "Unsupported platform") throw() | ||
} | ||
// abstract methods | ||
} | ||
|
||
// io/FileUnix | ||
FileUnix: class extends File { | ||
init: func (=path) {} | ||
// implement abstract methods for unix | ||
} | ||
|
||
// io/FileWin32 | ||
FileWin32: class extends File { | ||
init: func (=path) {} | ||
// implement abstract methods for Win32 | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|