Scripting language: Xmas (ii)

Source: Internet
Author: User

This article, to talk about the type system, and some of the garbage collector related content.

First, the basic type

Basic types of Xmas: Null, Boolean, Label, String, Ref, Function, Integer, Float, Decimal, Array, List, Set, Map, object;14, There are a number of other scripting languages, but these types are "atomic", one less, and somewhat inconvenient (but not incomplete, such as decimal to replace all arithmetic types; map can replace all container types). If you read the previous article, you will find a little bit different--a week ago, Xmas had only 13 basic types.

Yes, "Label" was just added last night (well, but after a period of thought); The Xmas represents: a compile-time constant, or an integer mapping of a string literal that can be named. There are two reasons for joining:

1, object and struct function, missing a suitable parameter type: object{Field:value}, Object ("field", value), this is the previous practice (of course, this conversion is done by the compiler); When we want pure handwriting, each field's name is replaced by a string, which is an unnatural way, not more natural: Object (field, value). Here "Field" is a label.

2, for the performance, with the label, we can use a lot of label at run time instead of string, this will have a considerable return (in fact, not too large; part of the string, is created in the compiler, and is shared).

The only thing that needs to be tangled up is: how do I create/declare a label?

Typical in other languages are: field (Ruby), ' field ' (Lisp); it's ugly, seriously. Originally Ruby ":" Can also be accepted, but Xmas ":" Already has several uses, then joins a will give the compiler to bring a certain burden (ambiguous syntax, processing needs some brain cells).

Then, think of "Unified type Creation" in Xmas: New Type ()/New type{}. The latter is the unified initialization syntax (such as map: New map{Val1:12}; not: New map (VAL:12)); then the label needs to support this form of creation, then it can:

    var new field; // Create a label ("field"), without ()/{}

Then there is the following object creation method:

    New Object // Unified Initialization    New Object (new// manual function call

This is cleaner than using strings, of course, there are compromises, after all, the label itself and other literal (variable, parameter, function name) Form no difference, but, we have to distinguish (otherwise, you must use a subordinate structure similar to unified initialization to distinguish)

It is important to note that the new itself is with the meaning of creating the object, there is no exception in Xmas, but the label is an exception, it was created at compile time, so there is no additional consumption.

Second, create

There are at least 3 ways to create each type in Xmas (except for the preceding label, which cannot be unambiguously stated): Literal, new Type (), New type{}, Type ().

The basic type is generally 4 (at least formally):

     A ;     New Integer (a);     New Integer {n};     Integer (a);

One of the puzzling things about this is: does new need to be? Yes:

1, only add new, you can use the unified initialization method (which is important for map and object).

2, only add new, the compiler will be able to know: you are creating an object, to be able to perform the appropriate additional processing (later).

3. Let yourself and others know that the code is in the creation of an object.

As for why not allow the compiler to identify the creation of the object itself (for example: var = Integer (12)); Unfortunately this is not possible:

    Integerfunctionreturn1;};     var Integer (a);

The creation function of an object in Xmas is not a keyword (nor is it possible, such as a custom class); So, the above code, the compiler does not know whether "integer (12)" is to create an integer, or call a function-in fact, the correct function is called. This is one of the costs of supporting functional programming: the static nature of function calls is not, because any variable can be a function.

So, new has a need for existence: it enforces the creation of an object, followed by the name of that type. Of course, with this information (to determine if it's an object creation), the compiler has more to do: the creation of custom types is optimized.

Essentially, the creation of a custom type requires the following complete four steps:

    //1. Create an empty object (similar to C + + allocated memory)obj =New Object();//This is a function call that can be added without "new"//2, set the class information (equivalent to C + + set virtual function table)Obj.class=New Class("AClass");//This is also a function call and does not require "new"//3. Calling the constructor of a custom classObj.__init ();//This field is newly added and it holds the constructor//4. Set the final property of the object    try_final(obj);//This is more complicated, and it's going to be later (related to GC)

This is also a complete case of using reflection (reflection); Of course, this is a manual approach and not a recommended approach. With new as a declaration, the compiler can map all of these operations directly to a call to a system function:

    class ("aclass"// use a function with the same name as the keyword "class"

Because it has the same name as the keyword, it cannot be called directly in the code; You can, of course:

    New Function ("class"//Creates a function, by means of the name     = func ("aclass  ");

Of course, this is not the point; the point is that if you don't use new to tell the compiler "This is the object being created," instead, use:

    // directly invoking the creation function of the class (generated by the compiler)

Of course, if there is no such thing as a variable named "AClass", the compiler can infer that this is an object creation, but I am lazy; and it is not recommended. More crucially, in order to identify "This is an object creation", the compiler needs to know the additional information: known to have a type called "AClass". Rather than, you can postpone some time.

Third, object-oriented

As we all know, object-oriented is just how the memory layout of the object is set (parent and subclass) and how the virtual function table is implemented.

In the front, we already know the virtual function table in Xmas: A field named "Class"-where all the information (member functions, type information) of the custom type is placed. So, what exactly is in ". Class"?

class aclass:xmas{function     aclass () {        this// Call the constructor of the parent class     }    function func () {}}

What kind of class does the above definition produce?

 class: ..... The parent class Xmas things .... __init=Function: Aclass.aclass//the AClass constructor__type =Function: AClass//The compiler generates the creation function (its internal invocation: Class ("AClass");)__name =String: "AClass"//type name__final =Boolean:true/false    //Final property of typeAClass = Function : aclass func=Function: Aclass.func//Custom Functions

A lot of things are obvious: The new __init is handy for creating objects with reflection, otherwise you need to do the following:

    .......     = Get_value (obj.class"aclass"//batch reflection creation, we may only know the type name in string form    obj.constructor ();    .......     // the above corresponds to:    Obj. AClass ();

About the virtual function table this thing, as long as you know there is such a thing, it can also be very natural to construct the corresponding. But another problem: the memory layout of objects has always been a big problem for object-oriented. In addition to C + + other languages use interface to solve this. Yes, as long as multiple inheritance is forbidden, the problem becomes simple.

For this Xmas, there is no suitable solution: Simple member overrides--the rename fields and functions of the parent class--are simply overwritten and inaccessible, even in the parent class's space. The reason, very simple I personally do not use the object-oriented features, so, will not expend energy to do .... Lazy cancer, late.

Of course, Xmas is more than that; we can easily construct an object by reflection, but perhaps we can:

    New Object ();    obj. class ;  // Is this a prank? 

Xmas does not allow this code to run; in the execution to "obj.class = 12;" , it detects if the "Rvalue" is really a class. This means that we are not able to create a new type manually (in a few days or so) through reflection. Xmas limits the ability of reflection to become "read-only," but it also disables the possibility of creating invalid objects-the "Class" field is an internal field that can only be used to place type information.

It should be added that the type information of the Xmas is generated on demand-the corresponding type information is constructed when the custom type is first created.

Iv. Final Attribute

In Xmas, an object has a triple meaning of "immutable":

1. Except for the container type (Array, List, Set, Map, Object), the other types are immutable.

2, the container type, has a configurable final property, and can only be set once: set it to "immutable" (the default is variable).

3, the custom type, inherits the 2nd at the same time (because it uses object as the container); There is an additional final property generated by the compiler (that is: class.__final).

For the 1th, it's easy to understand: Like a string in Java, it's immutable and will create a new string for any of its operations. Similarly, the immutable type in Xmas, too-you have no way to change the value inside an integer (this is a functional style). There are two sides to this:

1, immutability, means that any calculation will create a new object, rather than reuse, which undoubtedly adds to the burden of the GC (most typically a cursor in a loop, 10,000 cycles, need to create 10,000 cursors).

2, immutability, means that the object reuse does not have any burden; A string can be reused throughout the code without worrying about it being changed; instead, it reduces the burden on the GC (but not much less).

This is more significant for the compiler: at compile time, you can safely reuse any object (the compilation period will only create simple immutable objects) without worrying about being contaminated.

The 2nd, like the const modifier of C + +: The modified object is immutable, but the object that the pointer points to in its members cannot be limited. In the case of a language, such attributes are not necessarily present (many languages are not), and this immutable attribute is absolute-once "immutable" is set and immutable, the object is never mutable!

New array{'hh'2.2};  Final(list);   // set object to immutable list[1  // Error! Run-time throws an exception

3rd, it inherits the concept of the 2nd, but expands: once a custom object is created, it is automatically set to the final property (according to the value in Class.__final):

    try_final(obj);
  Equivalent to
  if (obj.__final) {
    Final (obj);
}

The purpose of the same is to accomplish the same purpose: Set the object to "immutable" and automatically.

So the only question is: Where does class.__final come from?

class classa{    function ClassA () {        this;    }} class classb:classa{    function ClassB () {}    function SetValue (val) {          this. Value = val;    }}

where classa.class._final = True, while classb.class.__final = False.  Why? In terms of the meaning of the field, it means that an instance of that type is allowed to be changed. Xmas, there is such a simple logic--if there is no function in the class definition that changes the contents of the "this", then the type is immutable.

Therefore, to define a mutable class, it is necessary to have a corresponding "setxxx" System class function. So, CLASSB has a function that changes the contents of this and is therefore mutable. Of course, any operation inside the constructor does not affect the final property-because the constructor is only called once.

V. GC

Why does a garbage collector appear here? Because, "final" itself is for the GC to exist.

The GC in front of Xmas is a token-based, generational collector; so, in order to accomplish a true generational: when you do a young GC, you don't tag objects of the old age (as much as possible). Xmas provides the final abstraction: A final object that is directly held by the object whose generational is not, from the old age to the younger generation, will only rise from the young generation to the old age.

This sentence is very abstract, it is broadly representative of:

     A ;     New object{Val:val};    Final (obj);    ....... GC ...    // 1  and Obj,val into the old age.    // 2  , obj is final, then obj cannot have a reference to the young generation (any moment)     ....... // because obj is an old age and does not have a reference to a young generation, you do not have to scan

As far as the result is concerned, when there are large-scale survivors (most of whom have been promoted to the old age; Because young cannot have a large number of objects), the proportion of objects that they need to scan is between 10:1~1000:1 (Xmas results) When you perform a youth GC. This effect is excellent, and the total GC time is reduced by 80%-90%.

Of course, this assumption is only true if there is a large number of immutable objects in the background. Xmas A lot of effort for this. For example, there are two ways to create an object: New object{}, new struct{}. The difference is that a struct creates an object that is set to be immutable. Xmas is exempt from memory management by GC, but it also gives the ability to interfere with GC, or, of course, the better work of the auxiliary GC (the final attribute of the Xmas custom class is the ability to automate assisted GC, which does not require manual intervention or not).

As for the reason? Because the GC is not a submodule of the Xmas, it is a completely separate system; it exists not just for Xmas (mostly), but for other modules in my library.

PS: Otherwise, additional technology is required to avoid a large number of older objects being scanned, and it has an additional cost.

Vi. Types of systems

Xmas has a keyword function that gets the object type: typeof. It returns something that is interesting: the function. In the earliest version, the string was returned (and, of course, the label can be considered now).

But returning functions can solve the problem more gracefully.

    New ClassA ();     if (typeof(obj) = = ClassA) {        print ('He he');    }

By returning the creation function of that type, we can write more straightforward and convenient code: not only the quotation marks of the string are exempt, but also:

    var typeof (obj) ("I ' m a param");

The above code creates a new instance of the obj type, even though we do not know what the type of obj is (the function is valuable as a first-value class).

Scripting language: Xmas (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.