Skip to content
/ KLP Public

Kinda Like Perl (KLP), aims to be an implementation of the core parts of Perl (Perl 1.0) on Python for use on iOS Pythonista - namely its StaSH shell.

License

Notifications You must be signed in to change notification settings

flash548/KLP

Repository files navigation

NAME

Kinda Like Perl (KLP)

- Note there's two branches:

- master

- rogue 

Master branch aims to be as close to possible as the original Perl 1.0 (except for the failed tests below).

Rogue branch adds some non-Perl1 features like say() and will have more and more non-Perl1 nice-to-haves.

USAGE

From within other source:

from Lexer import Lexer
from Parser import Parser
from AST import AST
from VM import VM

source = """
    print "Hello World from KLP!\n";
"""

lex = Lexer(source)
par = Parser(lex)
ast = par.parse()
vm = VM()
ast.emit(vm)
vm.run()

From command line to imitate that of perl itself:

chmod +x main.py
./main.py -e 'print "Hello World from KLP!\n";'

DESCRIPTION

This language is "Kinda Like Perl"... in that its syntax highly resembles that of Perl 1.0, and passes the majority of its test suite, but not all features are implemented and/or behave exactly like that of the real, official Perl 1.0. To have that, you need Perl.

This project came about while using Pythonista on iOS along with the StaSH shell. I wanted to have some ability to do some text processing/searching and come from a background of using Perl a lot on-the-job. While one could probably port Perl to iOS, I wanted all the capabilities already affored in Pythonista so I figured I could settle on something that brought Just Enough Perl (maybe I should've called the project that) to StaSH that I could do what I needed.

So I set about reimplementing core parts of Perl 1.0 in Python - deciding on 1.0 since it would be easier than something as complex as Perl 5.xx (..and easy it was not). I'm not a CS major nor one versed in creating computer languages, but I did learn a lot along the way (HIGHLY recommend starting here https://ruslanspivak.com/lsbasi-part1/ if you want to learn how to write a language).

Like I said, KLP does pass the majority of the Perl 1.0 test suite scripts, but that doesn't mean it has 1:1 behavior with Perl 1.0 - guarantee there's large bugs lurking around in the code base. There's also numerous built-ins not implemented some due to be added in the future but some partly due to the fact you can't use them anyways on iOS StaSH environemnt as its not a fully compatible Unix environment anyways.

Check back often, as I plan to actively keep developing on this...

Status

Here's a brief summary on its state of affairs:

- KLP does not output very meaningful compile-time or run-time errors. Most of the time if you get an exception/croak, check to see if you missed a semicolon or called a non-defined sub or built-in. (TODO: fix, but until then good luck)

- Doesn't allow '$ ' (blank register) as a variable name (but neither does Perl5), so that fails a test in "t/base.lex" in its original form...

- Does NOT even come close to the speed of real Perl. This is due to some MAJOR inefficiencies in the design of KLP. Not gonna worry about that at this time.

- Doesn't split quite like Perl. e.g. "split / */ " in real Perl causes string to split on whitespace and in between characters, since KLP relies on Python's regex engine, its kind of a hack, but it does pass "t/op.split"

- Doesn't currently allow subscripted variables (or hash variables) in interpolated strings... but then again Perl 1 didn't either (as told in its man page) I hope to change this soon.

- Doesn't *currently* assign (unpack) to array or hash elements

- Doesn't support 'format' built-in or any special variables associated with that

- Supports `backticks` and attempts to set $? accordingly

- List of perl1 functions not implemented: - fork, times, exec, system, chown, kill, select, write

- Here's the list of IMPLEMENTED perl1 functions:

print, length, join, keys, values, each, eval, open, close, die, eof, shift,
unshift, seek, tell, index, sprintf, crypt, chop, sleep, push, pop, split,
printf, ord, chr, int, hex, oct, localtime, gmtime, time, stat, substr, exp,
sqrt, log, chdir, chmod, umask, unlink, rename, link, exit

- List of special variables not implemented (or ignored):

- $[ (first index of lists is always 0 in KLP)

- $^, $-, $%, $~, $=, $# (format variables)

- $/

- Maybe better to list the ones that ARE supported:

- $_

- @_

- @ARGV

- %ENV

- $!

- $.

- $+

- $, (output field sep)

- $\ (output record sep)

- $0

- $1 thru 10

- $@

- No module support, again like Perl 1. Would be nice though...

- Doesn't support the Perl 1 "-P" option where script is put through the C preprocessor first

- Only supports -n and -e switches at this time, and only one (1) -e switch

- No support for %SIG hash (yet), but %ENV is supported

- Most tests pass in the test suite, but there are some remaining precedence issues

- No '..' operator yet...

GOTCHAS

- Remember calling a function in Perl 1.0 requires different syntax - use 'do'

sub test {
    print "Hi";
}

do test();

TESTS

This is how KLP stacks up to the original Perl 1.0 test suite

Note: Perl 1.0 test suite is available at Allison Randal's Perl 1.0 Golang implementation - https://github.com/allisonrandal/gunie

Test Name/Status/Remarks

base.cond :GO

base.lex :ALMOST => Fails Test #1 (Blank register)

base.if :GO

base.pat :GO

base.term :GO (Need to make a dummy file /etc/termcap for the last test)

cmd.elsif :GO

cmd.for :GO

cmd.mod :GO

cmd.subval :GO

cmd.while :GO

comp.cmdopt :GO

comp.multiline :GO

comp.script :GO

comp.term :GO

io.fs :GO

io.argv :ALMOST => Test #4 and #5 fail

io.print :GO

io.tell :GO

io.inplace :NOGO => NYI

op.each :GO

op.append :GO

op.auto :GO

op.chop :GO

op.do :GO

op.crypt :GO

op.cond :GO

op.goto :GO => Note: requires main.py to be symlinked to "./perl"

op.eval :ALMOST => Test #5 and #6 fails (KLP doesn't handle malformed m// specs yet)

op.int :GO

op.join :GO

op.list :NOGO => Doesn't support unpacking to array elements/hash elements yet

op.flip :NOGO => '..' range operator not implemented yet

op.exp :GO

op.pat :GO

op.push :GO

op.repeat :GO

op.oct :GO

op.sleep :GO

op.split :GO

op.stat :GO

op.sprintf :GO

op.subst :GO

op.unshift :GO

op.time :ALMOST => times() not implemented so fails test #1

cmd.cpp :Not Implemented/Tested => KLP doesn't support -P / preprocessor processing

comp.decl :Not Implemented/Tested => 'format' not supported

op.exec :Not Implemented/Tested

op.fork :Not Implemented/Tested

op.magic :Not Implemented/Tested => signals not supported

FILES

Lexer.py - The lexer/scanner class which produces tokens for the Parser

Parser.py - Parses the language grammar by consuming (expected) tokens, and produces an Abstract Syntax Tree (AST)

AST.py - Custom AST with all the various subclasses representing various contructs of the language. By 'walking' the tree, we call on each node's emit() method to emit its bytecodes and arguments into an instance of the virtual machine.

VM.py - Virtual Machine. Executes bytecodes and manages the expression stack and symbol/variable table(s). At this point everything's global and there's no scopes - in the full spirit of Perl 1.

DataStack.py - Wrapper around a Python list with size limiting and push() method

TokenType.py - Defines all the tokens we're working with as well as the built-in function names

main.py - The driver script to run KLP. This is probably was you want to symlink to as "perl".

Value.py - Everything we parse is a 'value'...everything on the stack is a 'value'. A Value is any object, but can be interpreted differently depending on the context - just like Perl's values.

TODO

Here's a list of some TODOs/nice-to-haves that would make KLP diverge from Perl 1.0:

- Borrow some Perl5 features (like hash declarations, opendir/readdir, chomp, say...)

- Support sockets (backed by Python socket lib)

- Better interoperability with Python as an embedded languages

- Document better!

- Fix stack leaks/speed

LICENSE

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

About

Kinda Like Perl (KLP), aims to be an implementation of the core parts of Perl (Perl 1.0) on Python for use on iOS Pythonista - namely its StaSH shell.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages