Advanced Magik Language

This page is intended for advanced programmers. See Magik Basic Language for more common language uses.

Compiling on the Fly

Do you need to load Magik code on the fly? Lets say a procedure is stored as a text join on an object and when you update the object, you want to let it run the procedure stored on the object.

The first thing you need is a handle to the string you want to "compile"
Then run this method: magik_rep.load_chunck(string.read_stream())

Stopping an Endless Loop on the Magik Prompt.

Have you started a (Near) endless loop on the Magik prompt? Here is a way to stop the loop.. You will need to open a Magik Input GUI from the opened application. In 3.X it was under Configuration or something like that. Once there type the following.

cli_thread.interrupt(_proc() _throw@wobbly _endproc)

From the Threads Manager, you can error the cli thread and it should stop the loop. Note the Threads Manager may only be available on 4.X releases.

Indirect Access to Globals

Have you wanted to write code that tests for the existence of a global variable without initializing the variable itself? You can use the following. Note the !current_package! could be replaced with packages such as sf_package.

!current_package![:global_symbol_name]

Another way. Good for getting procs too…

get_global_value(:!print_length!)
get_global_value(:startup)

You can "undeclare" a global by doing the following.

!current_package!.remove_key(:global_symbol_name)

Adding a Mixin during a session

If you need to create a mixin in a current session and want to add the mixin ancestry to existing exemplars that you can't recreate during the session (record exemplars for example), you can add them using the following magik

def_mixin(:whatever_mixin)
whatever_mixin.add_child(whatever_exemplar)

Getting Current Dynamics

Here is a way to get the available dynamic variables in your current thread.

_for k,v _over _thisthread.dynamic_environment(_true)
_loop
    show(k,v)
_endloop

Do you need to make a private method public?

Try this… Note you don't typically want to use this… But it is something to be aware of.

map_trail.method(:append_sectors_to_trail|()|).set_private(_false)

!!! THREAD !!! bpt on thread error

I was getting this when I was trying to do a code coverage analysis. The way to track this down is to add the following show() statement.

_pragma(classify_level=restricted)
_method coverage_analyser.insert_bpts_in(method)
show(method)
    method.value.set_breakpoint(0)
_endmethod
$

From the result you can add the problem method to coverage_analyser.excluded_code_vectors shared variable
_block
    _local ex << message_handler
    _for m _over {:human_string|()|
    }.fast_elements()
    _loop
        coverage_analyser.excluded_code_vectors.add(ex.method(m).value.code_vector)
    _endloop 
_endblock

Evaluating Strings into Magik results

You can evaluate a string like "_false" into a true Magik boolean.

MagikSF> !a << magik_text.new()
$
MagikSF> !a.add_last("_false")
$
MagiKSF> !a.evaluate() = _false
$
True

Temporarily Remove Method Functionality

Have you tried to use a method like split_by() only to see your leading and trailing spaces disappear? Here is a way you can overwrite the default behavior.. In this case we replace the trim_spaces() method with a simple procedure, run the split_by() and restore the original behavior.

    _local data
    _local str << " this is, a test ,  ,,"
    _local oProc << charindex_mixin.method(:trim_spaces|()|).value 
    _protect
        charindex_mixin.method(:trim_spaces|()|).value << 
                _proc()
                    >> _self 
                _endproc
        data<< str.split_by(%,,_true)
    _protection
        charindex_mixin.method(:trim_spaces|()|).value << oProc
    _endprotect

Lexicographic Sorting

Lexicographic sorting is sorting strings like in a dictionary. When sorting strings, there can be special characters like ï, é and so on. The special characters do not sort on the base character, but differently as is shown by the following example:

MagikSF> %ï _cf %j
$
False 
MagikSF> %i _cf %j
$
True 

Here is a simple solution to the Lexicographic sorting problem with special characters.
_block
    _local l_special_chars << property_list.new_with(%ï,%i, %ë,%e, %ö,%o)
    _local l_normalise << _proc(a) 
                      _import l_special_chars
                      _local l_result << ""
                      _for i_char _over a.fast_elementS()
                      _loop
                          l_result +<< l_special_chars[i_char].default(i_char)
                      _endloop
                      _return l_result
                  _endproc 
    _local l_list << {"mals", "maak", "mazk", "maïs"}
    _local l_sorted_list << sorted_collection.new_from(l_list,
                               _proc(a,b) 
                                   _import l_normalise 
                                   _return l_normalise(a) _cf l_normalise(b)
                               _endproc)
    print(l_sorted_list)
_endblock
$
sorted_collection(1,4):
1     "maak" 
2     "maïs" 
3     "mals" 
4     "mazk" 

Alternatively one may use text translators
text_converter.new(:cp1250, _false).translate(text_converter.new(:cp1250, _true).translate("maïs"))

Renaming Methods

You can rename a method using the following. This is great to implement customized code without modifying the original code. This saves lots of time when TSBs or upgrades are installed!

meth << exemplar.method(method_name)
newMeth << :sw!+method_name
exemplar.define_method(newMeth,meth.value,_false)
This functionality has been wrapped up in the attached fcsi_method_manip.magik file. Use fcsi_method_manip.fcsi_copy_method().

Packages

This needs a page of its own as there appears to be many things you can do with packages….

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License