Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

agent (5836)


Agent Zhang (章亦春) is a happy Yahoo! China guy who loves Perl more than anything else.

Journal of agent (5836)

Thursday April 28, 2005
06:54 AM

My First TXL Program

=from 2005.4.28.8:15.AM
=to ...4.28.8:55.AM

Yesterday afternoon I successfully wrote and tested my first TXL program that could perform algebraic expansion and bracket reduction. The whole source file implementing a parser, an AST transformer, and an implicit code generator was only 120 lines long. I saw how TXL manages to automate the complete process of compiler construction by combining the syntax of BNF and the concept of subtree pattern match and substitution (subtree insertion).

TXL may be considered as a typed programming language where the subtree pattern and the goal tree must be of the same type (in other words, be corresponding to the same BNF entity name). This feature guarantees that the final AST gained by various transformations always remain "well-formed". In contrast, In my Trop (Tree Operation) project developed in last term, I allowed the user to perform subtree substitution directly on physical AST data structure where the resulting tree may be valid in grammar, but by no means certain. The Canadians should be given credit for their creative work on unifying BNF and subtree insertion. I must say they did a good job!

My discovery of TXL on the web was quite unexpected. It was in the syntax file (.stx file) list on EditPlus official site that I first saw this exotic language's name!

Wednesday April 27, 2005
09:06 AM

Another Two Classes, Thief 0.02 Develop, and Real-Time Tesla

=from 2004.4.27.8:00.AM
=to ...4.27.9:05.AM

I gave Chen Xiaohui and her classmates another two welcomed lessons last Sunday. Wang Yongbin joined us, thus I had a boy student from then on. In the first class I decided to teach them English, especially its pronunciation, and I continued to use English on the blackboard in my second class on Database. All the four students were listening very carefully throughout the two and a half hour. They often raised very good questions.

Prompted by the lessons on Database, I restarted the Thief project last Saturday night and developed a web client tool named that could detect the distribution of student IDs, based on trials. It could extract the personal info from the web tables as well.

In contrast with the previous version of Thief, I decided no longer to save the HTML contents sent from the server to the local discs but to extract interesting info from the web pages and save them in a compact form at run-time. Experiments showed that we could consequently save 92~95% storage, which was pretty remarkable.

I intend to design and build a database using the student info provided by the Educational Administration System via Thief, in order to practice the concepts and techniques of database, which can be extremely attractive.

I also found it rather straightforward to extend the existing Tesla simulator developed last term to real-time applications. The only problem is how to synchronize the simulation clock and the real-world clock (or CPU clock). I thought the simplest solution to this is "pushing" simulation clock if and only if the time-stamp of the next simulation event is equal to or earlier than the current real-world time. In other words, we should raise the next event if and only if it's just up-to-date or already out-of-date.

All we discussed above mainly concern the back-end of Tesla. At the front-end, say, the Tesla HDL level, the matter of introducing bus signals has been under consideration. Borrowing the array structure from the implementation language can make our work minimal, just as what we did when we implemented the circuit component structure for Tesla HDL a few months ago.

That's what for the last few days; see you tomorrow!

Sunday April 24, 2005
05:50 AM

A Working Implementation of ac CirSys

=from 2005.4.21.8:05.AM
=to ...4.21.9:20.AM

It was really crazy yesterday. I did a lot of coding with madness and got a lot of things done. Now we have a working ac implementation for CirSys 0.08, with hundreds of unit tests, 60 integration tests ported directly from the dc system, and one "pure" ac integration test borrowed from the textbook "Engineering Circuit Analysis".

As the complexity of CirSys was increasing steadily, I finally decided to give up supports for MATLAB. There are too many limitations with MATLAB's Maple kernel, which leads to unacceptable cost of maintenance and limited flexibility. Once we get rid of this, we can exploit the advantage of Maple 9 features to the full without worrying compatibility issues.

For example, CirSys will by *default* generate the following Maple command,


in order to follow the standard notations used by engineers where we use "i" and "I" to denote time-varying currents and constant currents respectively, and prefer "j" to indicate the imaginary unit, say, sqrt(-1).

It will also be very handy if we implement some back-ends for the grepsol tool, which can perform transformations among rectangular form, polar form, and even exponential form of complex numbers. For instance, consider the following output of grepsol:

        i = 4+3*j
        i_2 = 5
        i_3 = 4*j

If we have a back-end named rec2pol that converts complex numbers from their rectangular form to polar form, it will generate the following Maple code accordingly:

        i = map(normal.evalc, polar(4+3*j));
        # ---
        i_2 = map(normal.evalc, polar(5));
        i_3 = map(normal.evalc, polar(4*j));

Oh, it's really a trivial thing to implement this back-end for us perl programmers!

I've noticed if we invoke cmaple.exe or cmaple9.exe too frequently, Maple server (mserver) will fail to start, which often cause my CirSys tester to crash. In that case, I have not choice but to terminate the mserver process by hand Windows Task Manager. Boring. It is desirable to wrap the OpenMaple interface as a full-fledged COM Server which will stick to only one instance in the OS environment regardless of the number of client processes. I'm guessing the ATL technology can be very helpful.

Wednesday April 20, 2005
02:13 AM

Learning Functional Programming

=from 2005.4.20.11:00.AM
=to ...4.20.11:45.AM

I'm completely out of battery and now moving very slowly in my work.

This morning I read the first few pages of the article "Why Functional Programming Matters" and was really amazed by the power of higher-order functions and lazy evaluations. However, I've still got a long way to go before I'm ready to bring functional programming to my every day's hacking. I've got so used to exploiting the advantage of "side-effects" to the full. And I even can't imagine what my life will be like when I'm not allowed to use global variables! The conversion by which functional programmers write their code seems rather peculiar to me, and I really need some more time to adapt my old thought to follow it as well.

I noted that there are plenty of sample codes available with Hugs distribution. Some source files are standard libraries, and some are demo programs. I consider it as a perfect source of learning materials. Of course, I should make full use of it, I think, but not today...

What a beautiful day today! Why not go out for a walk? I'd like to stay in the woods of the Southern Hills of Zhenjiang and enjoy the sunshine, the winds, and all the green creatures. So don't hesitate -- let me go now!

Tuesday April 19, 2005
02:47 AM

Parrot Learning and CirSys Class Library refactor

=from 2005.4.19.11:50.AM
=to ...4.19.12:05.PM

I've been reading the POD documents shipped with the Parrot distribution. It seems to me that the Parrot assembly language is quite simple. I regard it as something similar to 8086 assembly language but with powerful string handling capabilities and a funny register type named PMC (Parrot Magic Cookie). I think I'd offer my own implementation of Parrot assembler using perl for an exercise and I may write some toy compilers that target Parrot too.

I'm considering the issue of applying Parrot to my studies in university. Is it related to Computer Organization? Um, no obvious relationship, I'm afraid. Sigh.

I will add the last 8 integration tests (say, real-world problems from textbooks) to my CirSys tester. Thus we will have in total 60 integration tests this evening. That's great!

Now that I have a rather stable dc subsystem of CirSys, I don't feel like going any further with the dc stuff now. So I'm embarking on the design and implementation of the ac subsystem.

For the sake of apparent parallelity between dc and ac libraries, I think it's a bad idea to maintain two similar versions of and respectively. I'd come up with an alternative solution. I would only maintain one version of and one copy of for both dc and ac systems, but use a global variable, for instance, $Subsystem, to denote the current system (ac or dc) that is in effect. This sounds more feasible, but I soon realized that in essence I'm using branch statements (like "if" or "switch") to check the specialized "types" of object on the fly, which is considered to be a bad design from the viewpoint of OOP, or more precisely, from the view of polymorphism. A better design is using the inheritance feature of OO. Specifically, we can refactor the class hierarchy as following:

                |--- ac::Wire
                |--- dc::Wire

                |--- ac::Resistor
                |--- ac::Inductor
                |--- ac::Capacitor
                |--- ...
                |--- dc::Resistor
                |--- ...

The introduction of Steady::* class level can make the ac and dc subsystems share most of their common code, decreasing the cost of maintenance sharply, which is exactly what we are expecting. Cool!

Okay, when I register all the integration tests I prepared, I'll release CirSys 0.07 and rapidly move to version 0.08 so as to refactor the module structure and offer a working implementation of ac subsystem. Aha!

Monday April 18, 2005
08:19 AM

My First Lesson on Database

=from 2005.4.18.8:05.AM
=to ...4.18.9:05.AM

Yesterday morning I went to the southern campus of the Jiangsu University of Science and Technology giving Chen Xiaohui (Persian cat) and her roommates the first lesson on Visual FoxPro.

To my surprise, the girls managed to find an empty classroom for this class, which seems almost impossible in my university.

In the class, I introduced the basic concepts of database to the three girls by illustrating some real-world databases I had ever maintained. I tried my best to make the notions of application layer, logic layer, database tables, and etc. clear enough to the students who were all majored in Tourism. My first lesson ended up being a great success; the feedback from the students was quite satisfactory.

After the class, the girls and their monitor invited me to dinner in their school's dining hall. During the lunch, two other boys in their class came too, one of whom is named Wang Yongbin.

When we finished, Xiaohui asked Yongbin and one of her roommates, Huang Chunfang to see me off from the campus, and then she said goodbye to me, going to a meeting with their monitor.

Yongbin and Chunfang both refused to leave me until they saw I'd boarded the bus No. 18 and had been driven away. I clearly remember that when I asked them back home while we were waiting for a bus at the bus stop, Yongbin just replied, "Well, I know it's a boring experience to wait for a bus alone. So we'll stay with you untill the bus comes." I even couldn't say a single word at that moment; I was greatly moved.

In the afternoon I went on with my work on CirSys and managed to port all my 38 integration tests to MATLAB, which was really an important milestone for this project. From then on, the great number of MATLAB users can run CirSys without install anything else! Whee!

I'm wondering if the following Maple command works in MATLAB:


If it does, I will solve the naming problem involving the imaginary unit in a neat way.

Sunday April 17, 2005
07:48 AM

Potential Help from Classmates

=from 2005.4.16.8:05.AM
=to ...4.16.9:10.AM

I was delighted when Wan Xunxin and Zhang Xin respectively promised to plot circuit diagrams and contribute more integration test cases for my CirSys project. That's really very good news to me.

Wan Xunxin spent only one hour last night in learning how to draw circuit diagrams in MS Visio 2003, and he quickly got his way and produced high-quality pictures. Well done, Xin!

I plan to sketch out an Overview and a FAQ documents this weekend for CirSys, which are doubtlessly important to end-users. I should refer to Pugs' Overview and Parrot's FAQ first, I think.

Zhang Xin requested an AC implementation of CirSys. I suggested we test dc sub-system thoroughly before any ac-specific efforts. He happily accepted it.

This morning I'm going to raise the number of integration tests in the CirSys tester up to 60. Thanks to the basic implementation of @assume, which makes it possible. :^)

Last night I also tested CirSys' compatibility with MATLAB on Wang Longzhi's machine, which revealed a potential naming problem with identifier "i". Maple 9 uses capital letter "I" to denote the imaginary unit, say, sqrt(-1), whereas the maple interface provided by MATLAB prefers lowercase letter "i". This minor difference really hurt my tester seriously since I had used the name "i" extensively in my CIR scripts to indicate electric current quantities. Thus I have to play some naming tricks to fix this problem. For example, I may substitute "my_i" for all "i". Things will get more involved if we really want to say something referring to sqrt(-1) in CIR and we also hope our scripts can be accepted both by Maple and MATLAB. Perhaps we will have to say "sqrt(-1)" explicitly. Hopefully I'm able to think up an encompassing solution in the next few days.

Saturday April 16, 2005
04:10 AM

Basic implementation of @assume in CIR

=from 2005.4.15.2:15.PM
=to ...4.15.2:50.PM

This morning I promptly implement the new_layer and bye_layer functions for and later add the @assume and @end_assume directives to the CIR language. For simplicity, I didn't introduce an ad hoc module specially designed to deal with math model in the current version (0.07) of CirSys. I plan to move most of the code concerning equation and variable management in into an independent module named Math::Model in the next version. The core of the CirSys library thus will be cleaned up.

Currently wire definitions and element declarations are prohibited within @assume blocks. For example, the following CIR code is considered invalid at this moment:

                A, B: Vs2
                Resistor R1, R2
                B, C: R1, R2

However, this will eventually work in the next version of dc CirSys when I implement the ->destroy method for the Wire and Elem classes respectively. It can't be too difficult, I think.

With basic @assume support on hand, I'm able to get all the 60 test cases gleaned earlier working in my tester now. But I can't promise any further that subsequent circuit problems for Thevenin's Theorem will also work without complete support of assuming and backtracking.

There's no doubt that the CIR language is getting more and more mature. :P See you tomorrow!

03:25 AM

A Need of Change

=from 2005.4.15.8:20.AM
=to ...4.15.9:40.AM

I get bored in my process of improving dc CirSys 0.07. I'm a little anxious about time, since plotting circuit diagrams using MS Visio and preparing test cases from textbooks on circuit analysis are rather time-consuming. What shall I do? I've completely lost my way.

I guess I'm in need of a change. Shall I turn my attention to the other two courses, Mathematical Statistics and Computer Organization? If the answer is "yes", then how?

Indeed there are simulation projects related to these two courses and I've already devoted remarkable amount of efforts to applications concerning statistical and probabilistic simulation issues. However, these projects are still at very early stage. I'm worried now. :-(

I wonder if I can try another way to develop my projects. One sexy choice is implementing core algorithms using Haskell and writing compilers using TXL. Changing ways of doing things can make our lives more interesting, so why not? In the foreseeable future, I would rewrite most of my old perl projects by Perl 6. The accurate time depends on how fast Autrijus' Pugs is progressing. This kind of change seems to be less revolutionary compared with using Haskell directly though.

03:01 AM

Actual Implementation of Math::Model

=from 2005.4.14.8:00.AM
=to ...4.14.9:45.AM

Now I decide to sit down to consider seriously the matter of hacking on Math::Model. The basic code can be borrowed from the existing module. I think a procedural design will be appropriate here.

Math::Model should offer the following subroutines:

  • reg_eq
  • unreg_eq
  • reg_var
  • unreg_var
  • reg_eqs
  • get_eqs
  • get_vars
  • use_solve
  • new_layer
  • bye_layer

The last two functions are completely new. They provide the magic of assuming and backtracking. Once the user invokes new_layer, Math::Model will create a new layer (or a new "copy") for the math model, so any subsequent updates to the model won't spoil the original one. When the user calls bye_layer some time later, Math::Model will recover the model immediately back to the initial state just before the last new_layer calling. In other words, a call of bye_layer will effectively remove all the modifications to the math model (through reg_eq, unreg_var, etc.) since the last invocation of new_layer. This behavior is very similar to assuming and backtracking.

I finally prefer stack structures to do such trick. The implementation of bye_layer and new_layer is straightforward:

        our (@ModelStack, %Vars, @Equas);

        # new_layer: Create and enter a new layer.
        sub new_layer {
                push @ModelStack, {%Vars}, [@Equas];
                @Equas = ();

        # bye_layer: quit the current layer.
        sub bye_layer {
                my $ref = pop @ModelStack;
                return unless $ref;
                @Equas = @$ref;
                $ref = pop @ModelStack;
                %Vars = %$ref;

I hasten to ask the following question: What do we mean by a math model? A math model is composed of nothing but several equations, some optional inequalities, and a list of unknown variables. This basic concept should be clarified first at this point.

For each layer, there are two "localized" structures, %Vars and @Equas. %Vars is inherited directly from the outer layer (or parent layer), while @Equas holds only the equations built on the current layer due to efficiency considerations. The realization of the get_eqs function therefore needs a thorough rewrite accordingly:

        # get_eqs: get all the equations
        sub get_eqs {
                my @equas = get_eq_and_des();
                my @eqs = ();
                for (my $i=0; $i @equas; $i += 2) {
                        push @eqs, $equas[$i];
                return @eqs;

        # get_eq_and_des: get all the equations and corresponding descriptions:
        sub get_eq_and_des {
                my @equas;
                for (my $i = 1; $i @ModelStack; $i += 2) {
                        my $ref = $ModelStack[$i];
                        push @equas, @$ref;
                return (@equas, @Equas);

There is no need to modify the get_vars function originated from since the semantics of the %Vars structure does not change.

Now that we've got an implementation, it's time for us to write some tests...

I'm afraid I'm not a real XP programmer as I seldom write tests before any actual coding. Sigh.

With an excellent repertoire of math model management utilities, we can then happily implement the @assume language mechanism for our CIR scripts, which cannot be difficult. Aha!