# Axis-Lang
**Repository Path**: TommyLemon/Axis-Lang
## Basic Information
- **Project Name**: Axis-Lang
- **Description**: A programming language running on JVM. Powerful, Flexible, Safe and Simple.
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2018-08-05
- **Last Updated**: 2024-07-17
## Categories & Tags
**Categories**: scripting-language
**Tags**: None
## README
# Axis-Lang
A programming language running on JVM.
Powerful, Flexible, Safe and Simple.
[Designing...]
## Features
#### Support JSON like Schema
```javascript
Map map : {
'key0' : value0
'key1' : value1
...
}
```
#### Strong and static Type
#### Few system types
only Any, Bool, Int, Num, Str, Map and List
#### Type hint
if NAME_AUTHOR, User and an instance of User was defined like this:
```
final Str NAME_AUTHOR : 'Lemon'
class User {
Int id
Str name
Any extra
}
User user : {}
```
then when user or its fields were called, the IDE will automatically generate the Type behind instances:
user`@User`.name`@Str` : NAME_AUTHOR`@Str`
user`@User` : { `// user = new User().setId(1).setName("tommy");`
id`@Int` : 1 `// user.setId(1);`
name`@Str` : 'tommy' `// user.setName("tommy");`
extra : null `//no hint for Any, don't need it. user.setExtra(null);`
}
#### Safe type
```javascript
Int id : 0
Str name : null
id@Int.toStr()@Str // '0'
name@Str.length@Int //won't throw NullPoninterExeption but return null
name@Str.toUpperCase()@Str //won't throw NullPoninterExeption but return null
User user = null
user@User.name@Str : name@Str //automatically create user and name in user when they are null and the expression is for assign
PRINT(msg : user@User) //{ name : null }
```
#### Indexes for arrays
Positive index:
```javascript
arr.0 // arr[0]
arr.1 // arr[1]
arr.-1 // arr[arr.length - 1]
// arr.-0 //Forbidden, throw UnsupportedSyntaxError
```
If the index is out of arr's bounds [0, arr.length - 1],it will return null instead of throw IndexOutOfBoundsException.
If you want to stop the process when the case above happen, then you can:
```javascript
if arr.length@Int <= index@Int {
# IndexOutOfBoundsException(msg@Str : 'arr.length <= index! index is out of bounds!')
}
```
#### Default value for arguments
such as
```javascript
function(Type0 arg0, Type1 arg1 : null) {
...
}
```
then you can call
```javascript
function(arg0@Type0 : value0@Type0)
```
or
```javascript
function(
arg0@Type0 : value0@Type0
arg1@Type1 : value1@Type1
)
```
#### Return
the keyword 'return' is replaced with '^'
such as
```javascript
function() {
^ //return;
}
@NotNull
Any getNotNull(Any arg) {
^ arg = null ? {} ; arg //return arg == null ? new Object() : arg;
}
```
If you write 'return', the IDE will recommend '^'.
#### Lambda
Lambda is an anonymous callback
```javascript
function()
^() {
^() //callback.callback();
}
function() //这里比较难判断是声明还是调用,所以回调函数的 括号 () 也不能省
/*()*/ { //调用 function 时代码提示,一起自动生成
//do something
}
getNotNullAync(Any in)
^(@NotNull Any out) {
^(out : in = null ? {} ; in) //callback.callback(in == null ? new Object() : in);
}
getNotNullAync(in : null)
/*(@NotNull Str out)*/ { //调用 getNotNullAync 时代码提示,一起自动生成
//do something
}
Bool getNotNullAync(Any in)
^(@NotNull Any out) {
^(out : in = null ? {} ; in) //callback.callback(in == null ? new Object() : in);
^ in != null //return in != null;
}
Bool handled : getNotNullAync(in : null)
/*(@NotNull Str out)*/ { //调用 getNotNullAync 时代码提示,一起自动生成
//do something
}
T[] SORT(T[] list)
Int ^(T item0, T item1) {
if list@T[] = null | list@T[].size() <= 1 {
return list@T[].clone()
}
T[] sortedList : T[list@T[].size()][]
// ... add items to sortedList by an order
^(
/*item0@T : */ list.get(/*index@Int : */ index@Int)
/*item1@T : */ list.get(/*index@Int : */ index@Int + 1)
)
^ sortedList@T[]
}
Int[] sortedList : SORT(/*list@Int[] : */ [2, 5, 6, 1, 9, 3])
/*Int (Int item0, Int item1)*/ {
if item0@Int = item1@Int {
^ 0
}
if item0@Int = null {
^ item1@Int
}
if item1@Int = null {
^ item0@Int
}
^ item0@Int < item1@Int ? -1 ; 1
)
```
#### Throw
the keyword 'throw' is replaced with '#'
such as
```javascript
Any get(
Listable list
Int position
) # NullPoninterExeption, IndexOutOfBoundsException {
if list@Listable = null {
# NullPoninterExeption(msg@Str : 'list can not be null!') //throw new NullPoninterExeption("list can not be null!");
}
if position@Int = null {
# NullPoninterExeption(msg@Str : 'position can not be null!') //throw new NullPoninterExeption("position can not be null!");
}
if position@Int < 0 | position@Int >= list@Listable.length@Int {
# IndexOutOfBoundsException(msg@Str : 'position is out of bounds of list!') //throw new IndexOutOfBoundsException("position is out of bounds of list!");
}
^ list@Listable.get(position@Int : position@Int)
}
```
If you write 'throw' or 'throws', the IDE will recommend '#'.
#### Break
the keyword 'break' is replaced with '<<'
such as
```javascript
while true { //replace while(true) { ... }
PRINT(msg : 'while...')
<< //break;
}
```
If you write 'break', the IDE will recommend '>>'.
#### Continue
the keyword 'continue' is replaced with '>>'
such as
```javascript
until false { //replace do {...} while(...);
PRINT(msg : 'do while...')
Thread.sleep(time@Int : 1000)
>> //continue;
}
```
If you write 'continue', the IDE will recommend '>>'.
#### Default and anonymous getter and setter functions for fields
such as
```javascript
Str name {
override Str get() {
^ name@Str //return name;
}
override Str set(Str value) {
name@Str : value
^ this@User //return this;
}
} : null
```
private, protected or public fields have no getter or setter functions.
#### Expand fields
such as
```javascript
user@User.'isFriend' : true //isFriend is not a field decleared in User, so it must be covered with ''
log(msg@Str : 'id = ' + user@User.id@Int + '; isFriend = ' + user@User.'isFriend')
```
#### Package level funcions
such as
```javascript
package axis.api
abtract Bool isCorrect()
PRINT(Any msg) {
...
}
```
only suppor public abstract and public static functions.
#### Multiple extends and support Maps and functions
such as
```javascript
class User : Map, isCorrect { // public class User extends Map implements Interface$isCorrect {
override Bool isCorrect() {
^ true
}
}
```
the first one must be an Map Type, and the after Map Type can only supply CONSTANS and abstract functions.
#### '=' equal for any Types
```javascript
b@Bool = true // b.equals(true)
i@Int = 0 // i.equals(0)
s@Str = '' // s.equals('')
map@Map = {} // map.equals({})
list@List = [] // list.equals([])
user@User = User{} // user.equals(new User())
user@User = User{ // user.equals(new User().setId(1).setName('tommy'))
id@Int : 1 // setId(1)
name@Str : 'tommy' // setName('tommy')
}
```
### '+', '-' between Lists
```javascript
List list : [
1
2
3
]
list +: 4 // list.add(4)
PRINT(msg : list@List) // [1, 2, 3, 4]
list@List +: [
2
5
6
] //list.addAll([2, 5, 6])
PRINT(msg : list@List) // [1, 2, 3, 4, 2, 5, 6]
list@List -: <0> //list.remove(0);
PRINT(msg : list@List) // [3, 4, 2, 5, 6]
list@List -: [
0
5
] //list.remove((Object) 0); list.remove((Object) 5);
PRINT(msg : list@List) // [3, 4, 2, 6]
list@List -: 2 //list.remove((Object) 2)
PRINT(msg : list@List) // [3, 4, 6]
//forbidden list -: {0, 2} //list.remove(0) list.remove(2)
PRINT(msg : list@List.0@Int) // 3
PRINT(msg : list@List.'0'@Int) // 3
PRINT(msg : list@List.3@Int) // throw IndexOutOfBoundsException('index : 3, list.length : 3, index >: list.length !')
PRINT(msg : list@List.'3'@Int) // null
//forbidden PRINT(list.'a') //the index must be a number
list@List.4@Int : 4 // throw IndexOutOfBoundsException('index : 4, list.length : 3, index > list.length !')
list@List.'4'@Int : 4
PRINT(msg : list@List.'4'@Int) // 4
PRINT(msg : list@List) // [3, 4, 6, null, 4]
```
### '+', '-' between Maps
```javascript
Map map : {
'id' : 1
'sex' : 0
'name' : null
}
map@Map +: {
'name' : 'test'
'phone' : '123456789'
} // map.putAll({'name' : 'test', 'phone': '123456789'})
PRINT(msg : map@Map) // { 'id' : 1, 'sex' : 0, 'name' : 'test', 'phone' : '123456789' }
map@Map -: <'sex'> //map.remove('sex')
PRINT(msg : map@Map) // { 'id' : 1, 'name' : 'test', 'phone' : '123456789' }
map@Map -: 1 //map.removeValue(1);
PRINT(msg : map@Map) // { 'name' : 'test', 'phone' : '123456789' }
map@Map -: ['123456789'] //map.removeValues(['123456789']);
PRINT(msg : map@Map) // { 'name' : 'test' }
PRINT(msg : map@Map.name) // error, undefined filed name in map@Map!
PRINT(msg : map@Map.'name') // test
//forbidden PRINT(map.tag) // throw NotFoundException('could not find the key "tag" in map !')
PRINT(msg : map@Map.'tag') // null
//forbidden map.tag : 'Java'
map@Map.'tag' : 'Java'
PRINT(msg : map@Map.'tag') // Java
```
#### Loop
##### for
List
```javascript
Str[] NAMES : [
'name0'
'name1'
'name2'
]
//for(int i = 0; i < NAMES.length - 1; i ++)
for NAMES@Str[] { /*Int index, Str item*/ //automatically generated hint for arguments in the callback function
LOG(
tag@Str : 'FOR_EACH'
msg@Str : item@Str
)
}
//for(int i = NAMES.length - 1; i > 0; i --)
for NAMES@Str[] - { /*Int index, Str item*/ //automatically generated hint for arguments in the callback function
LOG(
tag@Str : 'FOR_EACH'
msg@Str : item@Str
)
}
//for(int i = 0; i < NAMES.length - 1; i += 2)
for NAMES@Str[] + 2 { /*Int index, Str item*/ //automatically generated hint for arguments in the callback function
LOG(
tag@Str : 'FOR_EACH'
msg@Str : item@Str
)
}
```
Map
```javascript
Map map : {
'key0' : value0@Int
'key1' : value1@Str
'key2' : value2@List
}
//Set> set = map.entrySet(); int index = 0; for(Entry e : set) { ... ; ... index ++ }
for map@Map { /*Int index, Entry e*/ //automatically generated hint for arguments in the callback function
LOG(
tag@Str : 'FOR_EACH'
msg@Str : 'key = ' + key@Str + '; value = ' + value
)
}
```
##### while
no parentheses
```javascript
//while (true) {}
while true {
}
```
##### until
'do-while' is replaced by 'until'
```javascript
//do {} while (true)
until false {
}
```
#### Assign value for final fields on any time
declare a Type
```javascript
class User : Map {
final Int id
final Str name
}
```
then call
```javascript
User user : {
id@Int : 1
name@Str : null
}
```
or
```javascript
User user : {} // User user = new User();
user@User.sex@Int : 0 // user.setSex(0);
user@User.{
id@Int : 1 // user.setId(1);
name@Str : null // user.setName(null);
}
```
#### Short and repeatable variable or constant names in the same scope
```javascript
Int id
List id
getId() {
^ id@Int // @Int is a type annotation generated by IDE, highlight and uneditable, generate code when export
}
setIdList(List id) {
this.id@List : id@List // @List is a type annotation generated by IDE, highlight and uneditable, generate code when export
}
getFromIdList(Int position) {
^ id@List.get(positoin@Int : position@Int)
}
```
If the type of a variable or a constant was changed, IDE will automatically change all the type annotations about it.
For example, you edit 'List id' and change it to 'Map id',
then all codes of 'id@List' will automatically become 'id@Map'.
```javascript
Map id
setIdList(List id) {
this.id@Map : id@List // Error!Type mismatch between id@Map and id@List !
}
getFromIdList(Int position) {
^ id@Map.get(key@Int : position@Int)
}
```
#### No Comma ',' and no semicolon ';'
replaced with escape character in many cases such as field and function declearations, value initiations, function calls.
```javascript
Str name : 'Axis'
Int version : 1
Map extra : {
'type' : 'Language'
'for' : 'Programming'
}
LOG(
Str tag
Str msg
) {
...
}
LOG(
tag@Str : 'Axis'
msg@Str : 'is a much better programming language than Java running on JVM.'
)
```
#### No 'static'
replaced with UPPER_CASE names.
static class
```javascript
class Outter : Map { //public class Outter extends Map {
class INNER { //public static class INNER {
}
}
```
static funciton
```javascript
MAIN(Str[] args : null) { //public static void main(Str[] args) {
}
```
static field
```javascript
final Str TAG : 'Axis' //public static final String TAG = "Axis";
```
#### No 'new' and no constructor
replaced with Type{}, such as
```javascript
User user : User{} //User user = new User();
```
#### No 'void' for functions
```javascript
call() { //public void call() {
}
Str callBack() { //public String cacallBackll() {
^ 'Title'
}
call() //call();
Str title : callBack() //String title = callBack();
```
#### No package
Auto set package for Axis files. And you don't need to write such code in Java
java
package org.axis.lang;
And if the path of an Axis file changed(Myabe the file was moved to another folder),
you don't need to edit the code above.
#### No public, private, protected, default
variables, fields, arguments or constants:
```javascript
Bool DEBUG : false //public static Boolean DEBUG = false;
Int _i : 1 //private Integer i = 1;
Str $s : 'Axis' //protected String s = "Axis";
```
class:
```javascript
class Outter { //public class Outter {
}
class _Inner { //private class Inner {
}
```
functions:
```javascript
call() { //public void call() {
}
Bool _connect() { //private Boolean connect() {
...
^ true
}
$onStart() { //protected void onStart() {
}
interface Logger {
log(Any msg) { //default void log(Object msg) {
PRINT(msg : msg)
}
}
```
variables:
```javascript
Int _i : 1 //private int i = 1;
Str $s : 'Axis' //protected String s = "Axis";
Bool DEBUG : false //public Boolean DEBUG = false;
```
#### No varargs
in Java, sometimes you need to use varargs to reduce codes like:
declear:
```java
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
...
}
```
then call:
```java
invoke(info, 1, 'Aixs', null);
```
while varargs is replaced with \[...] in Axis:
declear:
```javascript
Any invoke(
Any obj
List args
) # IllegalAccessException, IllegalArgumentException, InvocationTargetException {
...
}
```
you can call:
```javascript
invoke(
obj : info@Info
args@List : [
1
'Aixs'
null
]
)
```
#### Interface
1.Define an interface:
```javascript
interface Runnable {
run()
}
```
2.Define a method with argument, and the type of the argument is a interface above:
```javascript
runOnUiThread(Runnable action) {
...
}
```
3.Then you can call:
```javascript
runOnUiThread(
action@Runnable : { //type was a generated comment. No name means default name 'Runnable'.
run() {
...
}
}
)
```
Another expample:
```javascript
interface AdapterViewCallback {
View createView(
Int type
ViewGroup parent
)
bindView(
Int type
ItemView itemView
Int position
)
}
```
can be replaced function in package level
```javascript
abstract refresh(List list)
```
```javascript
class BaseAdapter : Adapter, AdapterViewCallback, refresh {
override View createView( //override is a keyword generated by IDE,you don't need and aren't allowed to write it
Int type
ViewGroup parent
) {
^ DemoView{}
}
override bindView( //override is a keyword generated by IDE,you don't need and aren't allowed to write it
Int type
ItemView itemView
Int position
) {
itemView.bindView(
type@Int : getItemViewType(position@Int : position@Int)
itemView@ItemView : getItem(position@Int : position@Int)
position@Int : position@Int
)
}
override refresh(List list) { //override is a keyword generated by IDE,you don't need and aren't allowed to write it
if list@List = null {
this.list@List : []
} {
this.list@List : list
}
}
}
```
#### If
replace if-else if-else, switch-case
if
```javascript
if a = 1 { // if
...
}
```
if-else
```javascript
if a = 1 { // if
...
} { // else
...
}
```
if-else-else if
```javascript
if a =
1 { // if
...
} 2 | a = 3 { // else if
...
} { // else
...
}
```
if-else-else if
```javascript
if a
= 1 { // if
...
} < 1 { // else if
...
} { // else
...
}
```
if-else-else if
```javascript
if
a = 1 { // if
...
} a < 1 & a != -1 { // else if
...
} { // else
...
}
```
#### Instanceof
replaced with 'is'
```javascript
true is Bool //true
0 is Str //false
```
If you write 'instanceof', the IDE will recommend 'is'.
#### Synchonized
replaced with 'sync'
```javascript
sync this {
//dosomething
}
sync Any.class {
//dosomething
}
```
If you write 'synchonized', the IDE will recommend 'sync'.
#### Callback
##### Abstract Method
1.Define an abstract method:
```javascript
run()
```
2.Define a method with argument, and the type of the argument is a abstract method above:
```javascript
runOnUiThread(run action) {
...
}
```
3.Then you can call:
```javascript
runOnUiThread(
action@run : () { // type was a generated comment. No name means default name 'run'.
...
}
)
```
#### Thread
childThread:
```javascript
childThread { // in a automatically recycler thread pool
// run on child thread
}
```
mainThread:
```javascript
childThread {
// run on child thread
mainThread {
// run on main thread
}
}
```