1 Star 1 Fork 0

TommyLemon / Axis-Lang

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

Axis-Lang

A programming language running on JVM.
Powerful, Flexible, Safe and Simple.
[Designing...]

Features

Support JSON like Schema

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

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:

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:

if arr.length@Int <= index@Int {
  # IndexOutOfBoundsException(msg@Str : 'arr.length <= index! index is out of bounds!')
}

Default value for arguments

such as

function(Type0 arg0, Type1 arg1 : null) {
  ...
}

then you can call

function(arg0@Type0 : value0@Type0)

or

function(
  arg0@Type0 : value0@Type0
  arg1@Type1 : value1@Type1
)

Return

the keyword 'return' is replaced with '^'
such as

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

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> 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

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

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

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

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

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

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

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

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

List<Int> list : [
  1
  2
  3
]

list +: 4 // list.add(4)

PRINT(msg : list@List<Int>) // [1, 2, 3, 4]

list@List<Int> +: [
  2
  5
  6
] //list.addAll([2, 5, 6])

PRINT(msg : list@List<Int>) // [1, 2, 3, 4, 2, 5, 6]

list@List<Int> -: <0> //list.remove(0);

PRINT(msg : list@List<Int>) // [3, 4, 2, 5, 6]

list@List<Int> -: [
  0
  5
] //list.remove((Object) 0);  list.remove((Object) 5);

PRINT(msg : list@List<Int>) // [3, 4, 2, 6]

list@List<Int> -: 2 //list.remove((Object) 2)

PRINT(msg : list@List<Int>) // [3, 4, 6]

//forbidden  list -: {0, 2} //list.remove(0) list.remove(2)

PRINT(msg : list@List<Int>.0@Int) // 3

PRINT(msg : list@List<Int>.'0'@Int) // 3

PRINT(msg : list@List<Int>.3@Int) // throw IndexOutOfBoundsException('index : 3, list.length : 3, index >: list.length !')

PRINT(msg : list@List<Int>.'3'@Int) // null

//forbidden  PRINT(list.'a') //the index must be a number

list@List<Int>.4@Int : 4 // throw IndexOutOfBoundsException('index : 4, list.length : 3, index > list.length !')

list@List<Int>.'4'@Int : 4

PRINT(msg : list@List<Int>.'4'@Int) // 4

PRINT(msg : list@List<Int>) // [3, 4, 6, null, 4]

'+', '-' between Maps

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

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

Map<Str, Any> map : {
  'key0' : value0@Int
  'key1' : value1@Str
  'key2' : value2@List
}

//Set<Entry<Str, Any>> set = map.entrySet();  int index = 0; for(Entry<K, V> e : set) { ... ; ... index ++ }
for map@Map<Str, Any> { /*Int index, Entry<Str, Any> 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

//while (true) {}
while true {
}
until

'do-while' is replaced by 'until'

//do {} while (true)
until false {
}

Assign value for final fields on any time

declare a Type

class User : Map {
  final Int id
  final Str name
}

then call

User user : {
  id@Int : 1
  name@Str : null
}

or

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

Int id
List<Int> id

getId() {
  ^ id@Int // @Int is a type annotation generated by IDE, highlight and uneditable, generate code when export
}
setIdList(List<Int> 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<Int, Int> id',
then all codes of 'id@List' will automatically become 'id@Map'.

Map<Int, Int> id

setIdList(List<Int> 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.

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

class Outter : Map {  //public class Outter extends Map {
  class INNER {  //public static class INNER {
  }
}

static funciton

MAIN(Str[] args : null) {  //public static void main(Str[] args) {
}

static field

final Str TAG : 'Axis'  //public static final String TAG = "Axis";

No 'new' and no constructor

replaced with Type{}, such as

User user : User{}  //User user = new User();

No 'void' for functions

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:

Bool DEBUG : false  //public static Boolean DEBUG = false;
Int _i : 1  //private Integer i = 1;
Str $s : 'Axis'  //protected String s = "Axis";

class:

class Outter {  //public class Outter {

}
class _Inner {  //private class Inner {
}

functions:

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:

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:

public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
  ...
}

then call:

invoke(info, 1, 'Aixs', null);

while varargs is replaced with [...] in Axis:
declear:

Any invoke(
  Any obj
  List args
) # IllegalAccessException, IllegalArgumentException, InvocationTargetException {
  ...
}

you can call:

invoke(
  obj : info@Info
  args@List : [
    1
    'Aixs'
    null
  ]
)

Interface

1.Define an interface:

interface Runnable {
  run()
}

2.Define a method with argument, and the type of the argument is a interface above:

runOnUiThread(Runnable action) {
  ...
}

3.Then you can call:

runOnUiThread(
  action@Runnable : { //type was a generated comment. No name means default name 'Runnable'.
    run() {
      ...
    }
  }
)

Another expample:

interface AdapterViewCallback {
  View createView(
    Int type
    ViewGroup parent
  )
  
  bindView(
    Int type
    ItemView itemView
    Int position
  )
}

can be replaced function in package level

abstract refresh(List list)
class BaseAdapter<T> : 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<T> list) {  //override is a keyword generated by IDE,you don't need and aren't allowed to write it
    if list@List<T> = null {
       this.list@List<T> : []
    }  {
      this.list@List<T> : list
    }
  }

}

If

replace if-else if-else, switch-case

if

if a = 1 {  // if
   ...
}

if-else

if a = 1 {  // if
   ...
}  {  // else
   ...
}

if-else-else if

if a =
   1 {  // if
   ...
}  2 | a = 3 {  // else if
   ...
}  {  // else
   ...
}

if-else-else if

if a
   = 1 {  // if
   ...
}  < 1 {  // else if
   ...
}  {  // else
   ...
}

if-else-else if

if
   a = 1 {  // if
    ...
}  a < 1 & a != -1 {  // else if
    ...
}  { // else
    ...
}

Instanceof

replaced with 'is'

true is Bool  //true
0 is Str  //false

If you write 'instanceof', the IDE will recommend 'is'.

Synchonized

replaced with 'sync'

sync this {
  //dosomething
}

sync Any.class {
  //dosomething
}

If you write 'synchonized', the IDE will recommend 'sync'.

Callback

Abstract Method

1.Define an abstract method:

run()

2.Define a method with argument, and the type of the argument is a abstract method above:

runOnUiThread(run action) {
  ...
}

3.Then you can call:

runOnUiThread(
  action@run : () {  // type was a generated comment. No name means default name 'run'.
    ...
  }
)

Thread

childThread:

childThread {  // in a automatically recycler thread pool
  // run on child thread
}

mainThread:

childThread {
  // run on child thread
  
  mainThread {
     // run on main thread
  }
}
MIT License Copyright (c) 2017 TommyLemon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

A programming language running on JVM. Powerful, Flexible, Safe and Simple. 展开 收起
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/TommyLemon/Axis-Lang.git
git@gitee.com:TommyLemon/Axis-Lang.git
TommyLemon
Axis-Lang
Axis-Lang
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891