混搭,语言的基础

图片

前言


该语言是我为教育目的而开发的。 我不认为它(目前)是一种完善的语言,但是也许将来它可以与竞争对手竞争。

如果您希望自己尝试使用它-下载项目存储库 ,在其中可以找到适合您的OS的项目的组装版本或自己组装。

本文将介绍一个小型项目手册,并考虑该语言的语法。

变量和隐式指针


在Mash中,每个变量都将一个指向对象的指针存储在内存中。 当将变量传递给方法,获取结果或对其进行简单操作时,将通过指向它们的指针来处理内存中的对象。

即 在下面的代码中,数组将作为指向早先创建的对象的指针传递给p(arr)方法。

proc p(arr): ... end proc main(): arr ?= [1, 2, 3, 4, 5] p(arr) end 

我认为,语言中无论是显式还是隐式的指针,都为它提供了更多的灵活性和功能性,尽管在某些情况下它会导致错误的产生。

临时变量和垃圾收集器


与类似的编程语言不同,Mash具有半自动垃圾收集器,该垃圾收集器基于时间值标签的机制,而不是对指针进行计数。

即 开发人员自己决定何时清除垃圾内存,在某些情况下也可以手动进行。

使用gc()调用垃圾收集,并从所有临时对象下释放内存。

许多带有变量的简单动作都会在内存中创建临时对象。

开发人员可以显式声明一个内存分配以进行进一步的处理,即 声明变量以供长期使用。

创建临时变量的示例:

 x ?= 10 

和未标记为垃圾收集器的变量:

 x ?= new(10) var x2 = 20 

使用gc()的示例:

 while a > b: doSomething(a, b) gc() end 

也可以手动释放内存:

 var a = 10, b = 20, c = 30 ... Free(a, b, c) 

可变可见区


Mash中的变量可以在本地和全局声明。

通过var语句在方法之间声明全局变量。 本地-内部方法以任何方式。

资料类型


在Mash中,动态输入。 自动检测/覆盖无符号和有符号数字,小数数字和字符串的数据类型。 另外,从简单的数据类型开始,数组(包括多级数组),枚举类型(与数组几乎相同),方法,逻辑数据类型,也许所有内容都受支持。

代码示例:

 x ?= 10 x += 3.14 x *= "3" x /= "2,45" x ?= [1, 2, 3.33, func1(1, 2, 3), "String", ["Enum type", 1, 2, 3], "3,14"] 

内省使您可以确定所需的变量类型:

 if typeof(x) == TypeInt: ... end 

数组和枚举


稀有任务不会强制开发人员在代码中声明下一个数组。
混搭支持由任意数量的级别组成的数组,+数组可以像树一样,即 子级别的大小可能在一个子级别上有所不同。

数组和枚举的声明示例:

 a ?= new[10][20] var b = new[10][20] c ?= [1, [], 3, 3.14, "Test", [1, 2, 3, 4, 5], 7.7, a, b, ["77", func1()]] var d = [1, 2, 3] 

通过new运算符声明的任何对象都不会标记为垃圾回收器。

数组与内存中的常规对象一样,可以通过调用Free()来释放
这样的转移工作非常方便。

例如,您可以传递给方法或从中返回一个变量的许多值:
 func doSomething(a, b, c): return [a+c, b+c] end 

赋值运算符


Mash中有多达3个赋值运算符。

  • ?=
    将变量分配给指向对象的指针(如果声明了变量但未在内存中存储指向对象的指针,则必须使用此运算符为其分配值)。
  • =
    正常分配。 通过变量中的指针将另一个对象的值分配给对象。
  • @ =
    通过指向该对象的显式指针为该对象分配值(稍后将对此进行讨论)。

数学和逻辑运算


当前支持的数学和逻辑运算列表:

  • +-*/
    无需评论。
  • \
    完全分开。

  • 其余部门。

  • 逻辑“与”。
  • |
    逻辑“或”。
  • ^
    逻辑“排他或”。

  • 逻辑“不”。
  • ++-
    递增和递减。
  • <<>>
    按位左移和右移。
  • ==<>> =<=
    逻辑比较运算符。

  • 检查对象是否属于枚举或数组。
    一个例子:
     if Flag in [1, 3, 5, 8]: ... 

显式指针


似乎,如果没有显式指针,为什么需要它们? 例如,检查变量A和B是否在内存中存储指向同一对象的指针。

  • @ -获取指向对象的指针,并将其放入变量(如对象)中。
  • -通过指针从变量中的对象获取对象。
    一个例子:
     a ?= ?b 

程序和功能


我决定对将值返回到过程和函数的方法进行语言分隔(如Pascal中一样)。

方法声明类似于以下示例:

 proc SayHello(arg1, arg2, argN): println("Hello, ", arg1, arg2, argN) end func SummIt(a, b): return a + b end 

语言构造


if..else..end构造示例。

 if <>: ... else: ... end 

对于循环。

 for([]; <>; [  ]): ... end 

一会儿 在迭代之前检查条件。

 whilst <>: ... end 

虽然。 循环不同于while循环,是在迭代后检查条件。

 until <>: ... end 

switch..case..end..else..end ...是用于创建逻辑分支的熟悉结构。

 switch <>: case < 1>: ... end case < 2>: ... end else: ... end 

OOP语言的类和元素


Mash实现了对类,继承,动态自省和反射,多态的支持。 即 支持一组标准的脚本语言。

考虑一个简单的类声明:

 class MyClass: var a, b proc Create, Free func SomeFunction end 

类声明不包含在其中声明的方法的实现。
该类的构造函数是Create方法。 作为破坏者-免费。

在类声明之后,您可以描述其方法的实现:

 proc MyClass::Create(a, b): $a ?= new(a) $b ?= new(b) end proc MyClass::Free(): Free($a, $b, $) end func MyClass::SomeFunction(x): return ($a + $b) / x end 

您可能会在代码的某些位置注意到$符号-使用这个符号我只是缩短了长的this->。 即 代码:

 return ($a + $b) / x ... Free($a, $b, $) 

等效于以下代码:
 return (this->a + this->b) / x ... Free(this->a, this->b, this) 

它包含一个指向该类实例的指针,该类的方法代表该实例被调用。

为了继承类的功能,您需要以这种方式描述新类的声明:

 class MySecondClass(MyClass): func SomeFunction end func MySecondClass::SomeFunction(x): return ($a - $b) / x end 

MySecondClass-将从祖先类拥有的祖先+ SomeFunction函数获得构造函数和析构函数,而该函数将被新类的函数覆盖。

要创建类实例,必须存在new运算符。

代码示例:

 a ?= new MyClass //     

 b ?= new MyClass(10, 20) //         

创建实例时可以确定类的实例的类型;因此,该语言中不存在类型转换。

内省使您可以确定类实例的类型,代码示例:

 x ?= new MyClass(10, 20) ... if x->type == MyClass: // -... end 

有时您需要使用一个类函数,并用新的函数覆盖它。 代码示例:

 func class::NewSomeFunction(x): return $x * $y * x end ... x ?= new MyClass(10, 20) x->SomeFunction ?= class::NewSomeFunction x->SomeFunction(33) // NewSomeFunction,     . 

结论


在本文中,我试图向我的创作介绍可能感兴趣的人。

感谢您的阅读。 等待评论。

Source: https://habr.com/ru/post/zh-CN437632/


All Articles