# HG changeset patch # User Paul Boddie # Date 1692725170 -7200 # Node ID 9350c36069619a234f600302fb70b224919a53fd # Parent 5f4b4a169398022451e793501b075e9671ef2188# Parent 1e7ccc84119f6b71d82aaf2d697627364b8b711f Merged changes from the trailing-data branch. diff -r 5f4b4a169398 -r 9350c3606961 common.py --- a/common.py Mon Feb 04 18:54:14 2019 +0100 +++ b/common.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,8 +3,7 @@ """ Common functions. -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, - 2017, 2018, 2019 Paul Boddie +Copyright (C) 2007-2019, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -563,6 +562,8 @@ self.next_temporary() t2 = self.get_temporary_name() self.next_temporary() + t3 = self.get_temporary_name() + self.next_temporary() node = compiler.ast.Stmt([ @@ -583,9 +584,10 @@ # try: # while True: # try: - # ... = () + # = () # except StopIteration: # raise LoopExit + # ... = # {n.body} # except LoopExit: # {n.else_} @@ -595,21 +597,47 @@ [compiler.ast.AssName(t2, "OP_ASSIGN")], compiler.ast.Getattr(compiler.ast.Name(t1), "next")), + # try: + compiler.ast.TryExcept( + + # while True: + compiler.ast.While( compiler.ast.Name("True"), compiler.ast.Stmt([ + + # try: + compiler.ast.TryExcept( + + # = () + compiler.ast.Assign( - [n.assign], + [compiler.ast.AssName(t3, "OP_ASSIGN")], compiler.ast.CallFunc( compiler.ast.Name(t2), [])), + + # except StopIteration: + # raise LoopExit + [(compiler.ast.Name("StopIteration"), None, compiler.ast.Raise(compiler.ast.Name("LoopExit")))], None), + + # ... = + + compiler.ast.Assign( + [n.assign], + compiler.ast.Name(t3)), n.body]), None), + + # except LoopExit: + # {n.else_} + # pass + [(compiler.ast.Name("LoopExit"), None, n.else_ or compiler.ast.Pass())], None) ]) @@ -1566,11 +1594,7 @@ "Return the module name containing the given type 'name'." - if name == "string": - modname = "str" - elif name == "utf8string": - modname = "unicode" - elif name == "NoneType": + if name == "NoneType": modname = "none" else: modname = name @@ -1581,12 +1605,7 @@ "Return the type name provided by the given Python value 'name'." - if name == "str": - return "string" - elif name == "unicode": - return "utf8string" - else: - return name + return name def get_builtin_class(name): diff -r 5f4b4a169398 -r 9350c3606961 docs/COPYING.txt --- a/docs/COPYING.txt Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/COPYING.txt Tue Aug 22 19:26:10 2023 +0200 @@ -1,8 +1,8 @@ Licence Agreement ----------------- -Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, - 2014, 2015, 2016, 2017 Paul Boddie +Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, + 2016, 2017, 2018, 2019 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff -r 5f4b4a169398 -r 9350c3606961 docs/tools/make_docs.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tools/make_docs.sh Tue Aug 22 19:26:10 2023 +0200 @@ -0,0 +1,30 @@ +#!/bin/sh + +THISDIR=`dirname "$0"` +INDIR="$THISDIR/../wiki" +OUTDIR="$THISDIR/../html" + +ROOT="Lichen" + +MAPPING='--mapping WikiPedia https://en.wikipedia.org/wiki/' +THEME='--theme mercurial' + +if [ "$1" = '--web' ] ; then + DOCINDEX= + shift 1 +else + DOCINDEX='--document-index index.html' +fi + +FILENAMES=${*:-'--all'} + +moinconvert --input-dir "$INDIR" \ + --input-page-sep '--' \ + --output-dir "$OUTDIR" \ + --root "$ROOT" \ + --format html \ + --macros \ + $DOCINDEX \ + $MAPPING \ + $THEME \ + $FILENAMES diff -r 5f4b4a169398 -r 9350c3606961 docs/tools/make_pages.sh --- a/docs/tools/make_pages.sh Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/tools/make_pages.sh Tue Aug 22 19:26:10 2023 +0200 @@ -56,7 +56,7 @@ BASENAME=`basename "$FILENAME"` PAGENAME=`echo "$BASENAME" | sed 's/--/\//g'` if [ "$PREFIX" ]; then - if [ "$PAGENAME" = "FrontPage" ]; then + if [ "$PAGENAME" = "Lichen" ]; then PAGENAME="$PREFIX" else PAGENAME="$PREFIX/$PAGENAME" diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Deduction --- a/docs/wiki/Deduction Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/Deduction Tue Aug 22 19:26:10 2023 +0200 @@ -89,7 +89,7 @@ //format=svg //transform=notugly digraph indexes { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Indexes"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Indexes"]; edge [tooltip="Indexes"]; rankdir=LR; @@ -142,7 +142,7 @@ //format=svg //transform=notugly digraph deduction { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Deduction"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Deduction"]; edge [tooltip="Deduction"]; rankdir=LR; @@ -192,7 +192,7 @@ //format=svg //transform=notugly digraph usage_to_types { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Usage to types"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Usage to types"]; edge [tooltip="Usage to types"]; rankdir=LR; @@ -249,7 +249,7 @@ //format=svg //transform=notugly digraph instance_providers { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Instance providers"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Instance providers"]; edge [tooltip="Instance providers"]; rankdir=LR; @@ -310,7 +310,7 @@ //format=svg //transform=notugly digraph assignments { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Attribute assignments"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Attribute assignments"]; edge [tooltip="Attribute assignments"]; rankdir=LR; diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/FrontPage --- a/docs/wiki/FrontPage Mon Feb 04 18:54:14 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -= Lichen = - -|| [[/Downloads|Downloads]] || [[#Language|Language]] || [[#Toolchain|Toolchain]] || [[#Rationale|Rationale]] || [[#Documents|Documents]] || - -Lichen is both a Python-like [[/Design|language]] and a -[[/Toolchain|toolchain]] for that language. - -Some objectives: - - * Perform analysis on programs to better understand program structure and - behaviour - * Develop code generation capabilities - * Provide a platform for experimentation independent of existing Python - language and library implementations - * Provide independence from Python language evolution - * Learn things about writing compilers - -Despite building on a long [[/History|history]] of experimentation, Lichen -still requires some [[/ToDo|work to be done]] for it to be more widely usable. - -<> -== Language == - -The Lichen language [[/Design|foregoes]] various dynamic aspects of Python to -provide a foundation upon which more predictable programs can be built, while -preserving essential functionality to make the core of the language seem very -much "like Python" (thus yielding the name "Lichen"). The general syntax is -largely identical to Python, with only certain syntactic constructs being -deliberately unsupported, largely because the associated features are not -desired. - -<> -== Toolchain == - -The Lichen [[/Toolchain|toolchain]] employs existing tokeniser and parser -software to obtain an abstract syntax tree which is then inspected to provide -data to support deductions about the structure and nature of a given program. -With the information obtained from these processes, a program is then -constructed, consisting of a number of source files in the target compilation -language (which is currently the C programming language). This generated -program may be compiled and run, hopefully producing the results intended by -the source program's authors. - -Lichen source files use the `.py` suffix since the language syntax is -superficially compatible with Python, allowing text editors to provide -highlighting and editing support for Lichen programs without the need to -reconfigure such tools. However, an alternative, recommended suffix is likely -to be introduced in future. - -<> -== Library == - -Unlike other Python compilation efforts, Lichen programs employ a newly-written -library that is distinct from the CPython standard library distribution and -completely independent from the CPython extension and object libraries on which -Python programs being run with CPython must depend. Thus, there is no -dependency on any `libpython` for run-time functionality. Since the parts of -the Python standard library that are written in Python tend to be rather -variable in quality, there has been no real inclination to re-use modules from -that particular source, noting that they would need modifying to be compatible -with Lichen, anyway. However, rewriting such modules provides opportunities to -"do things right": with some functionality being over twenty years old and in -bad shape, this is arguably something that should have been done for Python, -anyway. - -<> -== Rationale == - -Python has proven to be a readable, productive, comfortable-to-use and popular -programming language. However, as it has accumulated features, the precise -behaviour of programs making use of many of these features has become more -difficult to predict. Features added to provide even more convenience to the -programmer have often incurred run-time costs, introduced layers of -indirection, and have made programs even more inscrutable. Instead of -development tools reaching a point of being able to infer information about -programs, it has been suggested that programmers annotate their programs in -order to help tools understand those programs instead. Beyond superficial code -style analysis and providing tooltips in integrated development environments, -Python code analysis is often portrayed as a lost cause. - -By employing a refined language [[/Design|design]], Lichen aims to let each -program define its [[/Structure|structure]] conveniently, be readily -[[/Inspection|inspected]], and thus support [[/Deduction|deductions]] about the -use of the program's objects by the code. The result should be more predictable -programs that can be [[/Translation|translated]] to other, more efficient, -[[/Representations|representations]]. The Lichen toolchain should be able to -tell the programmer useful things about their programs that it may also be able -to make use of itself. It not only aims to report information about programs -that might be of interest to the developer, but it seeks to produce -functioning, translated programs that can actually be run. - -<> -== Document Index == - -<> diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/History --- a/docs/wiki/History Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/History Tue Aug 22 19:26:10 2023 +0200 @@ -71,7 +71,7 @@ == Current Work == It was with such realisations that a new project was effectively born. -Tentatively called "!PythonLight" but renamed to "Lichen" as the code matured, +Tentatively called "PythonLight" but renamed to "Lichen" as the code matured, the objectives now involved a simpler processing framework that merely attempted to catalogue structure members, to determine the origins of such members, and to record data flow within namespaces in order to determine diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Imports --- a/docs/wiki/Imports Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/Imports Tue Aug 22 19:26:10 2023 +0200 @@ -95,7 +95,7 @@ //format=svg //transform=notugly digraph mutual { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Mutually-dependent modules"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Mutually-dependent modules"]; edge [tooltip="Mutually-dependent modules"]; rankdir=LR; @@ -209,7 +209,7 @@ //format=svg //transform=notugly digraph imports { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Import dependencies"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Import dependencies"]; edge [tooltip="Import dependencies"]; rankdir=LR; diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Inspection --- a/docs/wiki/Inspection Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/Inspection Tue Aug 22 19:26:10 2023 +0200 @@ -179,7 +179,7 @@ //format=svg //transform=notugly digraph accesses { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Names and accesses"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Names and accesses"]; edge [tooltip="Names and accesses"]; rankdir=TB; @@ -316,7 +316,7 @@ //format=svg //transform=notugly digraph usage { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Name and attribute tracking"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Name and attribute tracking"]; edge [tooltip="Name and attribute tracking"]; rankdir=TB; diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Lichen --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/wiki/Lichen Tue Aug 22 19:26:10 2023 +0200 @@ -0,0 +1,95 @@ += Lichen = + +|| [[/Downloads|Downloads]] || [[#Language|Language]] || [[#Toolchain|Toolchain]] || [[#Rationale|Rationale]] || [[#Documents|Documents]] || + +Lichen is both a Python-like [[/Design|language]] and a +[[/Toolchain|toolchain]] for that language. + +Some objectives: + + * Perform analysis on programs to better understand program structure and + behaviour + * Develop code generation capabilities + * Provide a platform for experimentation independent of existing Python + language and library implementations + * Provide independence from Python language evolution + * Learn things about writing compilers + +Despite building on a long [[/History|history]] of experimentation, Lichen +still requires some [[/ToDo|work to be done]] for it to be more widely usable. + +<> +== Language == + +The Lichen language [[/Design|foregoes]] various dynamic aspects of Python to +provide a foundation upon which more predictable programs can be built, while +preserving essential functionality to make the core of the language seem very +much "like Python" (thus yielding the name "Lichen"). The general syntax is +largely identical to Python, with only certain syntactic constructs being +deliberately unsupported, largely because the associated features are not +desired. + +<> +== Toolchain == + +The Lichen [[/Toolchain|toolchain]] employs existing tokeniser and parser +software to obtain an abstract syntax tree which is then inspected to provide +data to support deductions about the structure and nature of a given program. +With the information obtained from these processes, a program is then +constructed, consisting of a number of source files in the target compilation +language (which is currently the C programming language). This generated +program may be compiled and run, hopefully producing the results intended by +the source program's authors. + +Lichen source files use the `.py` suffix since the language syntax is +superficially compatible with Python, allowing text editors to provide +highlighting and editing support for Lichen programs without the need to +reconfigure such tools. However, an alternative, recommended suffix is likely +to be introduced in future. + +<> +== Library == + +Unlike other Python compilation efforts, Lichen programs employ a newly-written +library that is distinct from the CPython standard library distribution and +completely independent from the CPython extension and object libraries on which +Python programs being run with CPython must depend. Thus, there is no +dependency on any `libpython` for run-time functionality. Since the parts of +the Python standard library that are written in Python tend to be rather +variable in quality, there has been no real inclination to re-use modules from +that particular source, noting that they would need modifying to be compatible +with Lichen, anyway. However, rewriting such modules provides opportunities to +"do things right": with some functionality being over twenty years old and in +bad shape, this is arguably something that should have been done for Python, +anyway. + +<> +== Rationale == + +Python has proven to be a readable, productive, comfortable-to-use and popular +programming language. However, as it has accumulated features, the precise +behaviour of programs making use of many of these features has become more +difficult to predict. Features added to provide even more convenience to the +programmer have often incurred run-time costs, introduced layers of +indirection, and have made programs even more inscrutable. Instead of +development tools reaching a point of being able to infer information about +programs, it has been suggested that programmers annotate their programs in +order to help tools understand those programs instead. Beyond superficial code +style analysis and providing tooltips in integrated development environments, +Python code analysis is often portrayed as a lost cause. + +By employing a refined language [[/Design|design]], Lichen aims to let each +program define its [[/Structure|structure]] conveniently, be readily +[[/Inspection|inspected]], and thus support [[/Deduction|deductions]] about the +use of the program's objects by the code. The result should be more predictable +programs that can be [[/Translation|translated]] to other, more efficient, +[[/Representations|representations]]. The Lichen toolchain should be able to +tell the programmer useful things about their programs that it may also be able +to make use of itself. It not only aims to report information about programs +that might be of interest to the developer, but it seeks to produce +functioning, translated programs that can actually be run. + +<> +== Document Index == + +<> diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Representations --- a/docs/wiki/Representations Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/Representations Tue Aug 22 19:26:10 2023 +0200 @@ -16,8 +16,8 @@ //format=svg //transform=notugly digraph attributes { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Attributes"]; - edge [fontsize="13.0",fontname="Helvetica",tooltip="Attributes"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Attributes"]; + edge [fontsize="13.0",fontname="sans-serif",tooltip="Attributes"]; rankdir=TB; attrA [label="attribute | { value | reference to object }",shape=record]; @@ -77,8 +77,8 @@ //format=svg //transform=notugly digraph wrappers { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Wrappers"]; - edge [fontsize="13.0",fontname="Helvetica",tooltip="Wrappers"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Wrappers"]; + edge [fontsize="13.0",fontname="sans-serif",tooltip="Wrappers"]; rankdir=TB; inst [label="
instance | { attr1 | reference to method } | { attr2 | value } | ...",shape=record]; @@ -104,8 +104,8 @@ //format=svg //transform=notugly digraph objects { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Objects"]; - edge [fontsize="13.0",fontname="Helvetica",tooltip="Objects"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Objects"]; + edge [fontsize="13.0",fontname="sans-serif",tooltip="Objects"]; rankdir=TB; instC [label="
instance of C | { 0 | reference to\ninstance table } | { __class__ | reference\nto C } | { a | value } | { b | value } | ...",shape=record]; diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Restarted --- a/docs/wiki/Restarted Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/Restarted Tue Aug 22 19:26:10 2023 +0200 @@ -262,8 +262,8 @@ //format=svg //transform=notugly digraph structures { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Instance and class structures"]; - edge [fontsize="13.0",fontname="Helvetica",tooltip="Instance and class structures"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Instance and class structures"]; + edge [fontsize="13.0",fontname="sans-serif",tooltip="Instance and class structures"]; rankdir=TB; instanceC [label="
instance of C |{ context of a | value of a }|{context of b | value of b }",shape=record]; @@ -285,8 +285,8 @@ //format=svg //transform=notugly digraph methods { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Method structures"]; - edge [fontsize="13.0",fontname="Helvetica",tooltip="Method structures"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Method structures"]; + edge [fontsize="13.0",fontname="sans-serif",tooltip="Method structures"]; rankdir=TB; classC [label="
class C | { context of m | uncallable for m } | ...",shape=record]; diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Structure --- a/docs/wiki/Structure Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/Structure Tue Aug 22 19:26:10 2023 +0200 @@ -29,7 +29,7 @@ //format=svg //transform=notugly digraph program { - node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Program structure"]; + node [shape=box,fontsize="13.0",fontname="sans-serif",tooltip="Program structure"]; edge [tooltip="Program structure"]; rankdir=LR; diff -r 5f4b4a169398 -r 9350c3606961 docs/wiki/Toolchain --- a/docs/wiki/Toolchain Mon Feb 04 18:54:14 2019 +0100 +++ b/docs/wiki/Toolchain Tue Aug 22 19:26:10 2023 +0200 @@ -73,12 +73,12 @@ which the `parser` module effectively is (as would the `ast` module also be if it were used here), with it typically being implemented as an extension module in a non-Python language (in C for CPython, in Java for Jython, and so on). -Fortunately, the !PyPy project implemented their own parsing module, -`pyparser`, that is intended to be used within the !PyPy environment together -with their own `ast` equivalent, but it has been possible to rework `pyparser` -to produce representations that are compatible with the `compiler` package, -itself being modified in various ways to achieve compatibility (and also to -provide various other conveniences). +Fortunately, the [[http://pypy.org/|PyPy]] project implemented their own +parsing module, `pyparser`, that is intended to be used within the PyPy +environment together with their own `ast` equivalent, but it has been possible +to rework `pyparser` to produce representations that are compatible with the +`compiler` package, itself being modified in various ways to achieve +compatibility (and also to provide various other conveniences). == Program Analysis == diff -r 5f4b4a169398 -r 9350c3606961 generator.py --- a/generator.py Mon Feb 04 18:54:14 2019 +0100 +++ b/generator.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Generate C code from object layouts and other deduced information. -Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie +Copyright (C) 2015-2019, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -48,10 +48,10 @@ int_type = "__builtins__.int.int" list_type = "__builtins__.list.list" none_type = "__builtins__.none.NoneType" - string_type = "__builtins__.str.string" + string_type = "__builtins__.str.str" tuple_type = "__builtins__.tuple.tuple" type_type = "__builtins__.core.type" - unicode_type = "__builtins__.unicode.utf8string" + unicode_type = "__builtins__.unicode.unicode" none_value = "__builtins__.none.None" @@ -1066,7 +1066,7 @@ # Special internal size member. elif attrname == "__size__": - structure.append("__INTVALUE(%d)" % attr) + structure.append("{.sizevalue=%d}" % attr) continue # Special internal key member. @@ -1263,18 +1263,51 @@ for name in parameters: l.append("__attr %s" % name) - print >>f_code, """\ + # Special-case the integer type. + + # Here, the __builtins__.int.new_int function is called with the + # initialiser's parameters. + + if path == self.int_type: + print >>f_code, """\ +__attr %s(__attr __self, __attr number_or_string, __attr base) +{ + return __fn___builtins___int_new_int(__NULL, number_or_string, base); +} +""" % ( + encode_instantiator_pointer(path), + ) + + # Special-case the string types. + + # Here, the __builtins__.str.new_str function is called with the + # initialiser's parameter. + + elif path == self.string_type: + print >>f_code, """\ +__attr %s(__attr __self, __attr obj) +{ + return __fn___builtins___str_new_str(__NULL, obj); +} +""" % ( + encode_instantiator_pointer(path), + ) + + # Generic instantiation support. + + else: + print >>f_code, """\ __attr %s(__attr __self%s) { return %s(__NEWINSTANCE(%s)%s); } """ % ( - encode_instantiator_pointer(path), - l and ", %s" % ",".join(l) or "", - encode_function_pointer(initialiser), - encode_path(path), - parameters and ", %s" % ", ".join(parameters) or "" - ) + encode_instantiator_pointer(path), + l and ", %s" % ",".join(l) or "", + encode_function_pointer(initialiser), + encode_path(path), + parameters and ", %s" % ", ".join(parameters) or "" + ) # Signature: __new_typename(__attr __self, ...) @@ -1332,6 +1365,6 @@ return 0; } -""" % encode_function_pointer("__builtins__.str.str") +""" % encode_instantiator_pointer("__builtins__.str.str") # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5f4b4a169398 -r 9350c3606961 inspector.py --- a/inspector.py Mon Feb 04 18:54:14 2019 +0100 +++ b/inspector.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,8 +3,7 @@ """ Inspect and obtain module structure. -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, - 2014, 2015, 2016, 2017, 2018 Paul Boddie +Copyright (C) 2007-2019, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -78,13 +77,13 @@ ref = self.get_builtin("module") self.set_name("__class__", ref) - self.set_name("__name__", self.get_constant("string", self.name).reference()) - self.set_name("__file__", self.get_constant("string", filename).reference()) + self.set_name("__name__", self.get_constant("str", self.name).reference()) + self.set_name("__file__", self.get_constant("str", filename).reference()) # Reserve a constant for the encoding. if self.encoding: - self.get_constant("string", self.encoding) + self.get_constant("str", self.encoding) # Get module-level attribute usage details. @@ -531,7 +530,7 @@ # Provide leafname, parent and context attributes. parent, leafname = class_name.rsplit(".", 1) - self.set_name("__name__", self.get_constant("string", leafname).reference()) + self.set_name("__name__", self.get_constant("str", leafname).reference()) if class_name != "__builtins__.core.function": self.set_name("__parent__") @@ -659,6 +658,9 @@ self.function_defaults[function_name] = [] for argname, default in compiler.ast.get_defaults(n): + if argname[0] == ".": + argname = argname[1:] + if default: # Obtain any reference for the default. @@ -678,7 +680,7 @@ # Define a leafname attribute value for the function instance. - ref = self.get_builtin_class("string") + ref = self.get_builtin_class("str") self.reserve_constant(function_name, name, ref.get_origin()) # Track attribute usage within the namespace. diff -r 5f4b4a169398 -r 9350c3606961 internal_tests/branches.py --- a/internal_tests/branches.py Mon Feb 04 18:54:14 2019 +0100 +++ b/internal_tests/branches.py Tue Aug 22 19:26:10 2023 +0200 @@ -687,4 +687,77 @@ bt.get_assignment_positions_for_branches("a", ar) names.append(bt.assignments["a"]) +# This demonstrates why the assignment in a "for" loop construct must appear +# outside the inner "try" body: null usage escapes the loop via the exception +# handler and the raise statement, even though the assignment would only be +# valid otherwise. + +# Equivalent to... +# +# try: +# while ...: +# try: +# a = ... +# except: +# raise ... +# a.p +# except: +# pass + +bt = branching.BranchTracker() +bt.new_branchpoint() # begin (try) +bt.new_branchpoint(True) # begin (while) +bt.new_branch(True) # while ... +bt.new_branchpoint() # begin (try) +a = bt.assign_names(["a"]) +bt.resume_abandoned_branches() # except +bt.abandon_branch() # raise +bt.shelve_branch() +bt.new_branch() # (null) +bt.shelve_branch() +bt.merge_branches() # end (try) +ap = bt.use_attribute("a", "p") +bt.resume_continuing_branches() +bt.shelve_branch(True) +bt.new_branch() # (null) +bt.shelve_branch() +bt.merge_branches() # end (while) +bt.resume_broken_branches() +bt.resume_abandoned_branches() # except +bt.shelve_branch() +bt.new_branch() # (null) +bt.shelve_branch() +bt.merge_branches() # end (try) + +print simple_usage(a) == \ + {'a' : set([('p',), ()])}, simple_usage(a) +print bt.get_assignment_positions_for_branches("a", ap) == [0], \ + bt.get_assignment_positions_for_branches("a", ap) +names.append(bt.assignments["a"]) + +# Equivalent to... +# +# b = ... +# while ...: +# a = ... +# a.p + +bt = branching.BranchTracker() +bt.new_branchpoint(True) # begin +b = bt.assign_names(["b"]) +bt.new_branch(True) # while ... +a = bt.assign_names(["a"]) +ap = bt.use_attribute("a", "p") +bt.resume_continuing_branches() +bt.shelve_branch(True) +bt.new_branch() # (null) +bt.shelve_branch() +bt.merge_branches() # end + +print simple_usage(a) == \ + {'a' : set([('p',)])}, simple_usage(a) +print bt.get_assignment_positions_for_branches("a", ap) == [0], \ + bt.get_assignment_positions_for_branches("a", ap) +names.append(bt.assignments["a"]) + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/__init__.py --- a/lib/__builtins__/__init__.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/__init__.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Simple built-in classes and functions. -Copyright (C) 2015, 2016, 2017, 2019 Paul Boddie +Copyright (C) 2015, 2016, 2017, 2019, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -68,9 +68,9 @@ from __builtins__.none import None, NoneType from __builtins__.notimplemented import NotImplemented, NotImplementedType from __builtins__.set import frozenset, set -from __builtins__.str import basestring, str, string +from __builtins__.str import basestring, str from __builtins__.tuple import tuple -from __builtins__.unicode import unicode, utf8string +from __builtins__.unicode import unicode # Functions. diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/buffer.py --- a/lib/__builtins__/buffer.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/buffer.py Tue Aug 22 19:26:10 2023 +0200 @@ -53,7 +53,7 @@ if isinstance(s, buffer): list_concat(self, s.__data__) - elif isinstance(s, string): + elif isinstance(s, str): list_append(self, s) else: list_append(self, str(s)) diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/character.py --- a/lib/__builtins__/character.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/character.py Tue Aug 22 19:26:10 2023 +0200 @@ -103,7 +103,7 @@ check_int(i) if 0 <= i <= 2097151: - return utf8string(unicode_unichr(i)) + return unicode(unicode_unichr(i)) else: raise ValueError, i diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/exception/base.py --- a/lib/__builtins__/exception/base.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/exception/base.py Tue Aug 22 19:26:10 2023 +0200 @@ -71,7 +71,11 @@ "An exception signalling the end of iteration." - pass + def __init__(self, .iterator=None): + + "Initialise the exception with the given 'iterator'." + + pass class ValueError(Exception): diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/float.py --- a/lib/__builtins__/float.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/float.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Floating point number objects. -Copyright (C) 2015, 2016, 2018 Paul Boddie +Copyright (C) 2015, 2016, 2018, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,7 +19,7 @@ this program. If not, see . """ -from __builtins__.unicode import utf8string +from __builtins__.unicode import unicode from native import isinstance as _isinstance, \ int_float, is_int, \ float_add, float_div, float_eq, float_ge, float_gt, \ @@ -194,7 +194,7 @@ "Return a string representation." - return utf8string(float_str(self)) + return unicode(float_str(self)) __repr__ = __str__ diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/int.py --- a/lib/__builtins__/int.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/int.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Integer objects. -Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie +Copyright (C) 2015, 2016, 2017, 2018, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,22 +19,55 @@ this program. If not, see . """ -from __builtins__.unicode import utf8string +from __builtins__.str import basestring +from __builtins__.unicode import unicode from native import get_maxint, get_minint, is_int, \ int_add, int_and, int_div, int_eq, int_ge, int_gt, \ int_lshift, int_le, int_lt, int_mod, int_mul, int_ne, \ int_neg, int_not, int_or, int_pow, int_rshift, int_str, \ int_sub, int_xor +def new_int(number_or_string, base=10): + + "Initialise the integer with the given 'number_or_string'." + + if is_int(number_or_string): + return number_or_string + elif isinstance(number_or_string, basestring): + return str_to_int(number_or_string, base) + else: + raise TypeError + +def str_to_int(value, base=10): + + "Decode the string 'value' using the given 'base'." + + # NOTE: Add support for lower and upper in the string classes. + + #value = value.lower() + len_value = len(value) + digits = "0123456789abcdefghijklmnopqrstuvwxyz" + + result = 0 + i = 0 + + while i < len_value: + c = value[i] + d = digits.index(c) + result = result * base + d + i += 1 + + return result + class int: "An integer abstraction." - def __init__(self, number_or_string=None): + def __init__(self, number_or_string=None, base=10): "Initialise the integer with the given 'number_or_string'." - # NOTE: To be implemented. + # Implemented by new_int above, invoked specially by the translator. pass @@ -245,7 +278,7 @@ "Return a string representation." - return utf8string(int_str(self)) + return unicode(int_str(self)) __repr__ = __str__ diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/iteration/iterator.py --- a/lib/__builtins__/iteration/iterator.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/iteration/iterator.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Iterator objects. -Copyright (C) 2015, 2016 Paul Boddie +Copyright (C) 2015, 2016, 2019 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,6 +39,6 @@ self.i += 1 return value except IndexError: - raise StopIteration() + raise StopIteration, self # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/set.py --- a/lib/__builtins__/set.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/set.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Set objects. -Copyright (C) 2015, 2016, 2017 Paul Boddie +Copyright (C) 2015, 2016, 2017, 2019 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -323,7 +323,7 @@ try: bucket = self.mapping.buckets[self.index] except IndexError: - raise StopIteration + raise StopIteration, self # Access the current item. If no such item exists, get another # bucket. diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/span.py --- a/lib/__builtins__/span.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/span.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Span-related objects. -Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie +Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -101,7 +101,7 @@ "Return the next item or raise a StopIteration exception." if not self.count: - raise StopIteration + raise StopIteration, self current = self.current self.current = self.current.__add__(self.step) diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/str.py --- a/lib/__builtins__/str.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/str.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ String objects. -Copyright (C) 2015, 2016, 2017 Paul Boddie +Copyright (C) 2015, 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,7 +24,7 @@ from __builtins__.types import check_int from native import isinstance as _isinstance, \ str_add, str_lt, str_gt, str_eq, str_ord, \ - str_substr + str_size, str_substr WHITESPACE = (" ", "\f", "\n", "\r", "\t") @@ -54,7 +54,7 @@ else: self.__data__ = None self.__key__ = None - self.__size__ = 0 + self.__size__ = None # Internal methods. @@ -158,7 +158,7 @@ "Return the number of bytes in this string." - return self.__size__ + return str_size(self.__size__) # General type methods. @@ -166,7 +166,7 @@ "Return whether the string provides any data." - return self.__size__.__bool__() + return str_size(self.__size__).__bool__() def __contains__(self, value): @@ -576,7 +576,7 @@ def upper(self): pass -class string(basestring): +class str(basestring): "A plain string of bytes." @@ -607,7 +607,7 @@ l = get_using(basestring.__get_multiple_items__, self)(start, end, step) return "".join(l) -def str(obj): +def new_str(obj): "Return the string representation of 'obj'." diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/stream.py --- a/lib/__builtins__/stream.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/stream.py Tue Aug 22 19:26:10 2023 +0200 @@ -144,7 +144,7 @@ # Encode text as bytes if necessary. When the encoding is not set, any # original encoding of the text will be applied. - if _isinstance(s, utf8string): + if _isinstance(s, unicode): s = s.encode(self.encoding) fwrite(self.__data__, s) diff -r 5f4b4a169398 -r 9350c3606961 lib/__builtins__/unicode.py --- a/lib/__builtins__/unicode.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/__builtins__/unicode.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Unicode objects. -Copyright (C) 2015, 2016, 2017 Paul Boddie +Copyright (C) 2015, 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -25,21 +25,58 @@ from native import str_add, unicode_len, unicode_ord, unicode_substr, \ isinstance as _isinstance -class utf8string(basestring): +class unicode(basestring): "A character string representation based on UTF-8." - def __init__(self, other=None, encoding=None): + def __init__(self, s, encoding=None, original=None): """ - Initialise the string, perhaps from 'other', with any original - 'encoding' indicated. + Initialise the string from 'other', employing any indicated 'encoding' + for the provided string data. + + If 'original' is indicated, this may be used to override the original + encoding. This is useful when the string data is already in UTF-8 + format, but where the original encoding needs to be communicated. """ - get_using(basestring.__init__, self)(other) - self.encoding = encoding self.length = None + # Initialise using another Unicode object. + + if _isinstance(s, unicode): + get_using(basestring.__init__, self)(s) + self.encoding = s.encoding + + # Initialise using suitable string data but with an explicit original + # encoding. + + elif original: + get_using(basestring.__init__, self)(s) + self.encoding = original + + # Initialise using string data having either UTF-8 or another encoding, + # converting to UTF-8 and retaining the encoding details as the original + # encoding. + + else: + # Obtain a string representation. + + s = s.__str__() + + # Convert the string to UTF-8. Even if the stated encoding is UTF-8, it + # needs to be validated. + + to_utf8 = Converter(encoding or "UTF-8", "UTF-8") + + try: + to_utf8.feed(s) + get_using(basestring.__init__, self)(str(to_utf8)) + finally: + to_utf8.close() + + self.encoding = encoding + def _binary_op(self, op, other, sizes=False): "Perform 'op' on this object and 'other' if appropriate." @@ -51,7 +88,7 @@ # Combining text with bytes. - if not _isinstance(other, utf8string): + if not _isinstance(other, unicode): s = self.encode() else: s = self @@ -72,7 +109,7 @@ # Combining text with bytes. - if not _isinstance(other, utf8string): + if not _isinstance(other, unicode): s = self.encode() else: s = self @@ -86,8 +123,8 @@ "Convert 'result' to a Unicode object if 'other' already is." - if _isinstance(other, utf8string): - return utf8string(result, self.encoding) + if _isinstance(other, unicode): + return unicode(result, None, self.encoding) else: return result @@ -188,15 +225,14 @@ elif nonempty: b.append(self) - if _isinstance(s, utf8string): + if _isinstance(s, unicode): encoding = None b.append(s) s = str(b) if encoding: - s = utf8string(s) - s.encoding = encoding + s = unicode(s, None, encoding) return s # Special implementation methods. @@ -204,9 +240,9 @@ def __get_single_item__(self, index): "Return the item at the normalised (positive) 'index'." - + self._check_index(index) - return utf8string(unicode_substr(self.__data__, self.__size__, index, index + 1, 1), self.encoding) + return unicode(unicode_substr(self.__data__, self.__size__, index, index + 1, 1), None, self.encoding) def __get_multiple_items__(self, start, end, step): @@ -224,29 +260,6 @@ raise ValueError(step) l = get_using(basestring.__get_multiple_items__, self)(start, end, step) - return utf8string("".join(l), self.encoding) - -def unicode(s, encoding): - - "Convert 's' to a Unicode object, interpreting 's' as using 'encoding'." - - if isinstance(s, utf8string): - return s - - # Obtain a string representation. - - s = s.__str__() - - # Convert the string to UTF-8. Even if the stated encoding is UTF-8, it - # needs to be validated. - - to_utf8 = Converter(encoding, "UTF-8") - - try: - to_utf8.feed(s) - return utf8string(str(to_utf8), encoding) - - finally: - to_utf8.close() + return unicode("".join(l), None, self.encoding) # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5f4b4a169398 -r 9350c3606961 lib/native/__init__.py --- a/lib/native/__init__.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/native/__init__.py Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Native library functions. -Copyright (C) 2011, 2015, 2016, 2017, 2018 Paul Boddie +Copyright (C) 2011, 2015-2018, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -51,7 +51,7 @@ from native.program import get_using from native.str import str_add, str_chr, str_eq, str_gt, str_lt, \ - str_ord, str_substr + str_ord, str_size, str_substr from native.system import exit, get_argv, get_path diff -r 5f4b4a169398 -r 9350c3606961 lib/native/str.py --- a/lib/native/str.py Mon Feb 04 18:54:14 2019 +0100 +++ b/lib/native/str.py Tue Aug 22 19:26:10 2023 +0200 @@ -8,7 +8,7 @@ non-core exceptions used by the native functions because they need to be identified as being needed by the program. -Copyright (C) 2011, 2015, 2016, 2017 Paul Boddie +Copyright (C) 2011, 2015, 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -32,6 +32,7 @@ def str_gt(data, other_data): return True or False def str_lt(data, other_data): return True or False def str_ord(data): return 0 +def str_size(size): return 0 def str_substr(data, start, end, step): return "" # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5f4b4a169398 -r 9350c3606961 lplc --- a/lplc Mon Feb 04 18:54:14 2019 +0100 +++ b/lplc Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ """ Lichen Python-like compiler tool. -Copyright (C) 2016, 2017, 2018 Paul Boddie +Copyright (C) 2016-2018, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -151,6 +151,7 @@ Some options may be followed by values, either immediately after the option (without any space between) or in the arguments that follow them: +-j Number of processes to be used when compiling -o Indicate the output executable name -W Show warnings on the topics indicated @@ -190,8 +191,7 @@ elif "--version" in args or "-V" in args: print >>sys.stderr, """\ lplc %s -Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, - 2014, 2015, 2016, 2017 Paul Boddie +Copyright (C) 2006-2018, 2021 Paul Boddie This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty. @@ -206,6 +206,7 @@ gc_sections = False ignore_env = False make = True + make_processes = [] make_verbose = True outputs = [] paramnames = [] @@ -232,6 +233,7 @@ elif arg in ("-E", "--no-env"): ignore_env = True elif arg in ("-g", "--debug"): debug = True elif arg in ("-G", "--gc-sections"): gc_sections = True + elif arg.startswith("-j"): l, needed = start_arg_list(make_processes, arg, 1) # "P" handled below. elif arg.startswith("--param-codes"): l, needed = start_arg_list(paramnames, arg, 1) elif arg.startswith("--param-locations"): l, needed = start_arg_list(paramlocations, arg, 1) @@ -353,7 +355,8 @@ # Compile the program unless otherwise indicated. if make: - make_clean_cmd = ["make", "-C", generated_dir, "clean"] + processes = make_processes and ["-j"] + make_processes or [] + make_clean_cmd = ["make", "-C", generated_dir] + processes + ["clean"] make_cmd = make_clean_cmd[:-1] retval = call(make_cmd, make_verbose) diff -r 5f4b4a169398 -r 9350c3606961 templates/native/buffer.c --- a/templates/native/buffer.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/buffer.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for buffer operations. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,13 +30,13 @@ { /* _data interpreted as buffer.__data__ */ __fragment *data = _data.seqvalue; - unsigned int size = 0, i, j, n; + __int size = 0, i, j, n; char *s; __attr o; /* Calculate the size of the string. */ for (i = 0; i < data->size; i++) - size += __TOINT(__load_via_object(__VALUE(data->attrs[i]), __size__)); + size += __load_via_object(__VALUE(data->attrs[i]), __size__).sizevalue; /* Reserve space for a new string. */ s = (char *) __ALLOCATE(size + 1, sizeof(char)); @@ -45,7 +45,7 @@ for (i = 0, j = 0; i < data->size; i++) { o = __load_via_object(__VALUE(data->attrs[i]), __data__); - n = __TOINT(__load_via_object(__VALUE(data->attrs[i]), __size__)); + n = __load_via_object(__VALUE(data->attrs[i]), __size__).sizevalue; memcpy(s + j, o.strvalue, n); /* does not null terminate but final byte should be zero */ j += n; } diff -r 5f4b4a169398 -r 9350c3606961 templates/native/common.c --- a/templates/native/common.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/common.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Common operations for native functions. -Copyright (C) 2016, 2017, 2018 Paul Boddie +Copyright (C) 2016, 2017, 2018, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -26,12 +26,12 @@ /* Utility functions. */ -__attr __new_str(char *s, int size) +__attr __new_str(char *s, __int size) { /* Create a new string and mutate the __data__, __size__ and __key__ attributes. */ - __attr attr = __NEWINSTANCE(__builtins___str_string); + __attr attr = __NEWINSTANCE(__builtins___str_str); __store_via_object(__VALUE(attr), __data__, (__attr) {.strvalue=s}); - __store_via_object(__VALUE(attr), __size__, __INTVALUE(size)); + __store_via_object(__VALUE(attr), __size__, (__attr) {.sizevalue=size}); __store_via_object(__VALUE(attr), __key__, __NULL); return attr; } @@ -55,8 +55,8 @@ __fragment *__fragment_append(__fragment *data, __attr value) { __fragment *newdata = data; - unsigned int size = data->size, capacity = data->capacity; - unsigned int n; + __int size = data->size, capacity = data->capacity; + __int n; /* Re-allocate the fragment if the capacity has been reached. */ if (size >= capacity) diff -r 5f4b4a169398 -r 9350c3606961 templates/native/common.h --- a/templates/native/common.h Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/common.h Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Common operations for native functions. -Copyright (C) 2016, 2017, 2018 Paul Boddie +Copyright (C) 2016, 2017, 2018, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -27,7 +27,7 @@ /* Utility functions. */ -__attr __new_str(char *s, int size); +__attr __new_str(char *s, __int size); __attr __new_list(__fragment *f); __attr __new_float(double n); __fragment *__fragment_append(__fragment *data, __attr value); diff -r 5f4b4a169398 -r 9350c3606961 templates/native/iconv.c --- a/templates/native/iconv.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/iconv.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for character set conversion. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -56,8 +56,8 @@ /* Obtain the string, start position, and remaining bytes from the state. */ char *inbuf = __load_via_object(__VALUE(f->attrs[0]), __data__).strvalue; - int start = __TOINT(f->attrs[1]); - int remaining = __TOINT(f->attrs[2]); + __int start = __TOINT(f->attrs[1]); + __int remaining = __TOINT(f->attrs[2]); /* Allocate a string for the output buffer using the remaining input size as a guide. */ diff -r 5f4b4a169398 -r 9350c3606961 templates/native/int.c --- a/templates/native/int.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/int.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for integer operations. -Copyright (C) 2016, 2017, 2018 Paul Boddie +Copyright (C) 2016, 2017, 2018, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,8 +39,8 @@ __attr __fn_native_int_int_add(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Test for overflow. */ if (((i > 0) && (j > 0) && (i > __MAXINT - j)) || @@ -55,8 +55,8 @@ __attr __fn_native_int_int_sub(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Test for overflow. */ if (((i < 0) && (j > 0) && (i < __MININT + j)) || @@ -71,8 +71,8 @@ __attr __fn_native_int_int_mul(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Test for overflow. */ if (((i > 0) && (j > 0) && (i > __MAXINT / j)) || @@ -89,8 +89,8 @@ __attr __fn_native_int_int_div(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Test for division by zero or overflow. */ if (j == 0) @@ -105,8 +105,8 @@ __attr __fn_native_int_int_mod(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Test for division by zero or overflow. */ if (j == 0) @@ -121,7 +121,7 @@ __attr __fn_native_int_int_neg(__attr __self, __attr self) { /* self interpreted as int */ - int i = __TOINT(self); + __int i = __TOINT(self); /* Test for overflow. */ if (i == __MININT) @@ -134,8 +134,8 @@ __attr __fn_native_int_int_pow(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); int k; errno = 0; @@ -157,8 +157,8 @@ __attr __fn_native_int_int_and(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ @@ -168,7 +168,7 @@ __attr __fn_native_int_int_not(__attr __self, __attr self) { /* self interpreted as int */ - int i = __TOINT(self); + __int i = __TOINT(self); /* Return the new integer. */ return __new_int(~i); @@ -177,8 +177,8 @@ __attr __fn_native_int_int_or(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ @@ -188,8 +188,8 @@ __attr __fn_native_int_int_xor(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ @@ -199,8 +199,8 @@ __attr __fn_native_int_int_lshift(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ @@ -210,8 +210,8 @@ __attr __fn_native_int_int_rshift(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return the new integer. */ /* NOTE: No overflow test applied. */ @@ -221,8 +221,8 @@ __attr __fn_native_int_int_le(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return a boolean result. */ return i <= j ? __builtins___boolean_True : __builtins___boolean_False; @@ -231,8 +231,8 @@ __attr __fn_native_int_int_lt(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return a boolean result. */ return i < j ? __builtins___boolean_True : __builtins___boolean_False; @@ -241,8 +241,8 @@ __attr __fn_native_int_int_ge(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return a boolean result. */ return i >= j ? __builtins___boolean_True : __builtins___boolean_False; @@ -251,8 +251,8 @@ __attr __fn_native_int_int_gt(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return a boolean result. */ return i > j ? __builtins___boolean_True : __builtins___boolean_False; @@ -261,8 +261,8 @@ __attr __fn_native_int_int_eq(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return a boolean result. */ return i == j ? __builtins___boolean_True : __builtins___boolean_False; @@ -271,8 +271,8 @@ __attr __fn_native_int_int_ne(__attr __self, __attr self, __attr other) { /* self and other interpreted as int */ - int i = __TOINT(self); - int j = __TOINT(other); + __int i = __TOINT(self); + __int j = __TOINT(other); /* Return a boolean result. */ return i != j ? __builtins___boolean_True : __builtins___boolean_False; @@ -281,14 +281,14 @@ __attr __fn_native_int_int_str(__attr __self, __attr self) { /* self interpreted as int */ - int i = __TOINT(self); + __int i = __TOINT(self); /* Employ a buffer big enough to fit the largest integer plus an extra character, a minus sign, and the null terminator. */ unsigned int n = (int) log10(__MAXINT) + 3; char *s = (char *) __ALLOCATE(n, sizeof(char)); - snprintf(s, n, "%d", i); + snprintf(s, n, "%ld", i); /* Return a new string. */ return __new_str(s, strlen(s)); diff -r 5f4b4a169398 -r 9350c3606961 templates/native/io.c --- a/templates/native/io.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/io.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for input/output. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -120,7 +120,7 @@ /* fp interpreted as FILE reference */ FILE *f = (FILE *) fp.datavalue; /* size interpreted as int */ - int to_read = __TOINT(size); + size_t to_read = __TOINT(size); char buf[to_read]; size_t have_read; int error; @@ -150,7 +150,7 @@ /* str.__data__ interpreted as string */ char *s = __load_via_object(__VALUE(str), __data__).strvalue; /* str.__size__ interpreted as int */ - int to_write = __TOINT(__load_via_object(__VALUE(str), __size__)); + size_t to_write = __load_via_object(__VALUE(str), __size__).sizevalue; size_t have_written = fwrite(s, sizeof(char), to_write, f); int error; @@ -182,7 +182,7 @@ /* fd interpreted as int */ int i = __TOINT(fd); /* n interpreted as int */ - int to_read = __TOINT(n); + size_t to_read = __TOINT(n); char buf[to_read]; ssize_t have_read; char *s; @@ -207,7 +207,7 @@ /* str.__data__ interpreted as string */ char *s = __load_via_object(__VALUE(str), __data__).strvalue; /* str.__size__ interpreted as int */ - int size = __TOINT(__load_via_object(__VALUE(str), __size__)); + size_t size = __load_via_object(__VALUE(str), __size__).sizevalue; ssize_t have_written; errno = 0; diff -r 5f4b4a169398 -r 9350c3606961 templates/native/list.c --- a/templates/native/list.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/list.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for list operations. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,7 +30,7 @@ __attr __fn_native_list_list_init(__attr __self, __attr size) { /* size interpreted as int */ - unsigned int n = __TOINT(size); + __int n = __TOINT(size); __attr attr = {.seqvalue=__new_fragment(n)}; /* Return the __data__ attribute. */ @@ -42,7 +42,7 @@ /* _data interpreted as list.__data__ */ __fragment *data = _data.seqvalue; /* size interpreted as int */ - unsigned int n = __TOINT(size); + __int n = __TOINT(size); data->size = n; return __builtins___none_None; @@ -66,9 +66,9 @@ __fragment *data = __load_via_object(__VALUE(self), __data__).seqvalue; __fragment *other_data = other.seqvalue; __fragment *newdata = data; - unsigned int size = data->size, capacity = data->capacity; - unsigned int other_size = other_data->size; - unsigned int i, j, n = size + other_size; + __int size = data->size, capacity = data->capacity; + __int other_size = other_data->size; + __int i, j, n = size + other_size; /* Re-allocate the fragment if the capacity has been reached. */ if (n >= capacity) @@ -91,7 +91,7 @@ __attr __fn_native_list_list_len(__attr self, __attr _data) { /* _data interpreted as list.__data__ */ - unsigned int size = _data.seqvalue->size; + __int size = _data.seqvalue->size; /* Return the new integer. */ return __new_int(size); @@ -107,7 +107,7 @@ /* _data interpreted as list.__data__ */ __attr *elements = _data.seqvalue->attrs; /* index interpreted as int */ - int i = __TOINT(index); + __int i = __TOINT(index); return elements[i]; } @@ -117,7 +117,7 @@ /* _data interpreted as list.__data__ */ __attr *elements = _data.seqvalue->attrs; /* index interpreted as int */ - int i = __TOINT(index); + __int i = __TOINT(index); /* Set the element. */ elements[i] = value; diff -r 5f4b4a169398 -r 9350c3606961 templates/native/locale.c --- a/templates/native/locale.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/locale.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for locale handling. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -43,7 +43,7 @@ length = strlen(result); out = __ALLOCATE(length + 1, sizeof(char)); - strncpy(out, result, length); + strcpy(out, result); return __new_str(result, length); } @@ -64,7 +64,7 @@ length = strlen(result); out = __ALLOCATE(length + 1, sizeof(char)); - strncpy(out, result, length); + strcpy(out, result); return __new_str(result, length); } diff -r 5f4b4a169398 -r 9350c3606961 templates/native/str.c --- a/templates/native/str.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/str.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for string operations. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,9 +33,9 @@ /* _data, other interpreted as string.__data__ */ char *s = _data.strvalue; char *o = other.strvalue; - /* _size, othersize interpreted as int */ - int ss = __TOINT(_size), os = __TOINT(othersize); - int n = ss + os; + /* _size, othersize interpreted as size */ + __int ss = _size.sizevalue, os = othersize.sizevalue; + __int n = ss + os; char *r = (char *) __ALLOCATE(n + 1, sizeof(char)); memcpy(r, s, ss); @@ -90,7 +90,12 @@ /* _data interpreted as string.__data__ */ char *s = _data.strvalue; - return __new_int((unsigned int) s[0]); + return __new_int((__int) s[0]); +} + +__attr __fn_native_str_str_size(__attr __self, __attr _size) +{ + return __new_int(_size.sizevalue); } __attr __fn_native_str_str_substr(__attr __self, __attr _data, __attr start, __attr end, __attr step) @@ -98,15 +103,15 @@ /* _data interpreted as string.__data__ */ char *s = _data.strvalue, *sub; /* start interpreted as int */ - int istart = __TOINT(start); + __int istart = __TOINT(start); /* end interpreted as int */ - int iend = __TOINT(end); + __int iend = __TOINT(end); /* step interpreted as int */ - int istep = __TOINT(step); + __int istep = __TOINT(step); /* Calculate the size of the substring. */ size_t resultsize = ((iend - istart - (istep > 0 ? 1 : -1)) / istep) + 1; - int to, from; + size_t to, from; /* Reserve space for a new string. */ sub = (char *) __ALLOCATE(resultsize + 1, sizeof(char)); diff -r 5f4b4a169398 -r 9350c3606961 templates/native/str.h --- a/templates/native/str.h Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/str.h Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for string operations. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -27,6 +27,7 @@ __attr __fn_native_str_str_gt(__attr __self, __attr _data, __attr other); __attr __fn_native_str_str_eq(__attr __self, __attr _data, __attr other); __attr __fn_native_str_str_ord(__attr __self, __attr _data); +__attr __fn_native_str_str_size(__attr __self); __attr __fn_native_str_str_substr(__attr __self, __attr _data, __attr start, __attr end, __attr step); /* Module initialisation. */ diff -r 5f4b4a169398 -r 9350c3606961 templates/native/system.c --- a/templates/native/system.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/system.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for system operations. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff -r 5f4b4a169398 -r 9350c3606961 templates/native/tuple.c --- a/templates/native/tuple.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/tuple.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for tuple operations. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -32,7 +32,7 @@ __attr __fn_native_tuple_tuple_init(__attr __self, __attr size) { /* size interpreted as int */ - int n = __TOINT(size); + __int n = __TOINT(size); /* Return the __data__ attribute. */ if (n) return (__attr) {.seqvalue=__new_fragment(n)}; diff -r 5f4b4a169398 -r 9350c3606961 templates/native/unicode.c --- a/templates/native/unicode.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/native/unicode.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Native functions for Unicode operations. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,9 +39,9 @@ else return 0; } -static unsigned int nextpos(char *s, unsigned int size, unsigned int bytestart) +static __int nextpos(char *s, __int size, __int bytestart) { - unsigned int i = bytestart; + __int i = bytestart; while (i < size) { @@ -53,9 +53,9 @@ return i; } -static unsigned int prevpos(char *s, unsigned int bytestart) +static __int prevpos(char *s, __int bytestart) { - unsigned int i = bytestart; + __int i = bytestart; while (i > 0) { @@ -73,9 +73,9 @@ { /* _data interpreted as string.__data__ */ char *s = _data.strvalue; - /* _size interpreted as int */ - int size = __TOINT(_size); - unsigned int i, c = 0; + /* _size interpreted as size */ + __int size = _size.sizevalue; + __int i, c = 0; for (i = 0; i < size; i++) if (boundary(s[i])) @@ -89,9 +89,9 @@ { /* _data interpreted as string.__data__ */ char *s = _data.strvalue; - /* _size interpreted as int */ - int size = __TOINT(_size); - unsigned int i, c = 0, v; + /* _size interpreted as size */ + __int size = _size.sizevalue; + __int i, c = 0, v; for (i = 0; i < size; i++) { @@ -123,21 +123,21 @@ { /* _data interpreted as string.__data__ */ char *s = _data.strvalue, *sub; - /* _size interpreted as int */ - int ss = __TOINT(_size); + /* _size interpreted as size */ + __int ss = _size.sizevalue; /* start interpreted as int */ - int istart = __TOINT(start); + __int istart = __TOINT(start); /* end interpreted as int */ - int iend = __TOINT(end); + __int iend = __TOINT(end); /* step interpreted as int */ - int istep = __TOINT(step); + __int istep = __TOINT(step); /* Calculate the number of characters. */ - size_t nchar = ((iend - istart - (istep > 0 ? 1 : -1)) / istep) + 1; - unsigned int indexes[nchar]; + __int nchar = ((iend - istart - (istep > 0 ? 1 : -1)) / istep) + 1; + __int indexes[nchar]; - unsigned int c, d, i, to, from, lastbyte = 0; - int resultsize = 0; + __int c, d, i, to, from, lastbyte = 0; + __int resultsize = 0; /* Find the indexes of the characters. */ if (istep > 0) @@ -197,7 +197,7 @@ { /* value interpreted as int */ int i = __TOINT(value); - unsigned int resultsize; + __int resultsize; char *s; if (i < 128) resultsize = 1; diff -r 5f4b4a169398 -r 9350c3606961 templates/progops.c --- a/templates/progops.c Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/progops.c Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Operations depending on program specifics. -Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie +Copyright (C) 2015-2019, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -49,7 +49,7 @@ /* Generic internal data allocation. */ -__fragment *__new_fragment(unsigned int n) +__fragment *__new_fragment(__int n) { /* Allocate space for the list. */ @@ -62,9 +62,9 @@ return data; } -void __newdata_sequence(unsigned int number, __fragment *data, __attr args[]) +void __newdata_sequence(__int number, __fragment *data, __attr args[]) { - unsigned int i; + __int i; /* Copy the given number of values. */ @@ -74,7 +74,7 @@ data->size = number; } -__attr __newdata_list(unsigned int number, __attr args[]) +__attr __newdata_list(__int number, __attr args[]) { __attr self = __NEWINSTANCE(__builtins___list_list); __fragment *data = __new_fragment(number); @@ -86,7 +86,7 @@ return self; } -__attr __newdata_tuple(unsigned int number, __attr args[]) +__attr __newdata_tuple(__int number, __attr args[]) { /* Allocate the tuple and fragment together. */ @@ -103,7 +103,7 @@ } #ifdef __HAVE___builtins___dict_dict -__attr __newdata_dict(unsigned int number, __attr args[]) +__attr __newdata_dict(__int number, __attr args[]) { __attr self = __NEWINSTANCE(__builtins___dict_dict); @@ -171,6 +171,13 @@ __Raise(__new___builtins___core_UnderflowError(__NULL)); } +void __raise_value_error(__attr value) +{ +#ifdef __HAVE___builtins___exception_base_ValueError + __Raise(__new___builtins___exception_base_ValueError(__NULL, value)); +#endif /* __HAVE___builtins___exception_base_ValueError */ +} + void __raise_zero_division_error() { __Raise(__new___builtins___core_ZeroDivisionError(__NULL)); @@ -316,10 +323,11 @@ { __ref value; - /* Integers can be used directly as truth values. */ + /* Non-zero integers yield a non-zero result. Since the integer type can be + larger than int, a conversion is performed. */ if (__INTEGER(attr)) - return __TOINT(attr); + return __TOINT(attr) ? 1 : 0; /* Test against True and False explicitly. If necessary, invoke the bool function with the object and test against True. */ diff -r 5f4b4a169398 -r 9350c3606961 templates/progops.h --- a/templates/progops.h Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/progops.h Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Operations depending on program specifics. -Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie +Copyright (C) 2015-2019, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,10 +31,10 @@ /* Generic internal data allocation. */ -__fragment *__new_fragment(unsigned int n); +__fragment *__new_fragment(__int n); -__attr __newdata_list(unsigned int number, __attr args[]); -__attr __newdata_tuple(unsigned int number, __attr args[]); +__attr __newdata_list(__int number, __attr args[]); +__attr __newdata_tuple(__int number, __attr args[]); #define __newliteral___builtins___list_list(NUM, ...) __newdata_list(NUM, __ARGS(__VA_ARGS__)) #define __newliteral___builtins___tuple_tuple(NUM, ...) __newdata_tuple(NUM, __ARGS(__VA_ARGS__)) @@ -42,7 +42,7 @@ /* Potentially superfluous operations. */ #ifdef __HAVE___builtins___dict_dict -__attr __newdata_dict(unsigned int number, __attr args[]); +__attr __newdata_dict(__int number, __attr args[]); #define __newliteral___builtins___dict_dict(NUM, ...) __newdata_dict(NUM, __ARGS(__VA_ARGS__)) #endif @@ -56,6 +56,7 @@ void __raise_overflow_error(); void __raise_unbound_method_error(); void __raise_underflow_error(); +void __raise_value_error(__attr value); void __raise_zero_division_error(); void __raise_type_error(); diff -r 5f4b4a169398 -r 9350c3606961 templates/types.h --- a/templates/types.h Mon Feb 04 18:54:14 2019 +0100 +++ b/templates/types.h Tue Aug 22 19:26:10 2023 +0200 @@ -1,6 +1,6 @@ /* Runtime types. -Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie +Copyright (C) 2015-2019, 2021 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -23,6 +23,7 @@ program specifically. */ #include +#include /* Include the special instance position value. The pos member of __obj refers to the special type attribute for classes, indicating which position holds @@ -70,12 +71,18 @@ typedef union __attr __attr; typedef __obj * __ref; +/* Introduce an integer type that is interoperable with the size type. */ + +typedef ssize_t __int; + +/* Attribute value interpretations. */ + typedef union __attr { /* General attribute members. */ __ref value; /* attribute value */ - int intvalue; /* integer value data (shifted value, tagged) */ + __int intvalue; /* integer value data (shifted value, tagged) */ /* Special case attribute members. */ @@ -88,6 +95,7 @@ char * strvalue; /* string value */ __fragment * seqvalue; /* sequence data */ void * datavalue; /* object-specific data */ + __int sizevalue; /* object-specific size */ } __attr; typedef struct __obj @@ -109,17 +117,18 @@ typedef struct __fragment { - unsigned int size, capacity; + __int size, capacity; __attr attrs[]; } __fragment; -#define __FRAGMENT_SIZE(NUMBER) ((NUMBER) * sizeof(__attr) + 2 * sizeof(unsigned int)) +#define __FRAGMENT_SIZE(NUMBER) ((NUMBER) * sizeof(__attr) + 2 * sizeof(__int)) /* Attribute interpretation. */ -#define __NUM_TAG_BITS 1 -#define __TAG_INT 0b1 -#define __INTEGER(ATTR) ((ATTR).intvalue & __TAG_INT) +#define __NUM_TAG_BITS 2 +#define __TAG_INT 0b01 +#define __TAG_MASK 0b11 +#define __INTEGER(ATTR) (((ATTR).intvalue & __TAG_MASK) == __TAG_INT) /* Attribute value setting. */ @@ -129,10 +138,10 @@ /* Attribute as instance setting. */ -#define __INTVALUE(VALUE) ((__attr) {.intvalue=((VALUE) << __NUM_TAG_BITS) | __TAG_INT}) +#define __INTVALUE(VALUE) ((__attr) {.intvalue=(((__int) VALUE) << __NUM_TAG_BITS) | __TAG_INT}) #define __TOINT(ATTR) ((ATTR).intvalue >> __NUM_TAG_BITS) -#define __MAXINT ((1 << ((sizeof(__attr) * 8) - 1 - __NUM_TAG_BITS)) - 1) -#define __MININT (-(1 << ((sizeof(__attr) * 8) - 1 - __NUM_TAG_BITS))) +#define __MAXINT ((((__int) 1) << ((sizeof(__int) * 8) - 1 - __NUM_TAG_BITS)) - 1) +#define __MININT (-(((__int) 1) << ((sizeof(__int) * 8) - 1 - __NUM_TAG_BITS))) /* Argument lists. */ diff -r 5f4b4a169398 -r 9350c3606961 test_all.sh --- a/test_all.sh Mon Feb 04 18:54:14 2019 +0100 +++ b/test_all.sh Tue Aug 22 19:26:10 2023 +0200 @@ -3,7 +3,7 @@ # This tool runs the toolchain for each of the tests, optionally building and # running the test programs. # -# Copyright (C) 2016, 2017 Paul Boddie +# Copyright (C) 2016, 2017, 2021 Paul Boddie # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -20,6 +20,8 @@ PROGNAME=$0 OPTION=$1 +shift 1 +MAKE_OPTIONS="$*" LPLC="./lplc" DATADIR="_main.lplc" @@ -53,7 +55,7 @@ if [ "$OPTION" = '--help' ] ; then cat 1>&2 < ] Run the toolchain over all tests in the tests directory. @@ -87,6 +89,11 @@ Build and output logs are stored in the _results directory with the .build and .out suffixes employed respectively, one of each kind for each generated program. + +The make options can be used to specify things like the number of processes +employed to perform a build of each program. For example: + +$PROGNAME --build -j8 EOF exit 1 fi @@ -193,7 +200,7 @@ echo " (build)..." 1>&2 if ! make -C "$DATADIR/_generated" clean > "$BUILDLOG" 2>&1 || \ - ! make -C "$DATADIR/_generated" > "$BUILDLOG" 2>&1 ; then + ! make -C "$DATADIR/_generated" $MAKE_OPTIONS > "$BUILDLOG" 2>&1 ; then exit 1 fi diff -r 5f4b4a169398 -r 9350c3606961 tests/identity.py --- a/tests/identity.py Mon Feb 04 18:54:14 2019 +0100 +++ b/tests/identity.py Tue Aug 22 19:26:10 2023 +0200 @@ -1,7 +1,7 @@ -print isinstance("string", string) # True +print isinstance("string", str) # True print isinstance("string", int) # False print isinstance(123, int) # True -print isinstance(123, string) # False +print isinstance(123, str) # False print class A: diff -r 5f4b4a169398 -r 9350c3606961 tests/int.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/int.py Tue Aug 22 19:26:10 2023 +0200 @@ -0,0 +1,30 @@ +i = int(123) +j = 123 +print i, j, i == j # 123 123 True +k = 456 +print i, k, i == k # 123 456 False +h = int(789) +print i, h, i == h # 123 789 False +print j, h, j == h # 123 789 False + +try: + a = int("a") # should raise an exception +except ValueError, exc: + print 'int("a") failed:', exc.value + +try: + a = int("!") # should raise an exception +except ValueError, exc: + print 'int("!") failed:', exc.value + +a = int("a", 16) +b = int("123") +print a # 10 +print b, i, b == i # 123, 123, True +print b, j, b == j # 123, 123, True + +a_is_int = isinstance(a, int) +j_is_int = isinstance(j, int) + +print a_is_int # True +print j_is_int # True diff -r 5f4b4a169398 -r 9350c3606961 tests/numbers.py --- a/tests/numbers.py Mon Feb 04 18:54:14 2019 +0100 +++ b/tests/numbers.py Tue Aug 22 19:26:10 2023 +0200 @@ -18,7 +18,7 @@ j = -2 ** 29 print j # -536870912 print hex(j) # -0x20000000 -print oct(j) # -05000000000 +print oct(j) # -04000000000 print i + j # 0 diff -r 5f4b4a169398 -r 9350c3606961 tests/unicode.py --- a/tests/unicode.py Mon Feb 04 18:54:14 2019 +0100 +++ b/tests/unicode.py Tue Aug 22 19:26:10 2023 +0200 @@ -18,37 +18,37 @@ s2 = b"\xe6\xf8\xe5" print "ISO-8859-15 values:" print s2 # זרו -print s2.__class__ # __builtins__.str.string +print s2.__class__ # __builtins__.str.str print len(s2) # 3 s3 = "\xe6\xf8\xe5" print "ISO-8859-15 values:" print s3 # זרו -print s3.__class__ # __builtins__.str.string +print s3.__class__ # __builtins__.str.str print len(s3) # 3 s4 = b"\u00e6\u00f8\u00e5" print "Untranslated values:" print s4 # \u00e6\u00f8\u00e5 -print s4.__class__ # __builtins__.str.string +print s4.__class__ # __builtins__.str.str print len(s4) # 18 s5 = b"\346\370\345" print "ISO-8859-15 values:" print s5 # זרו -print s5.__class__ # __builtins__.str.string +print s5.__class__ # __builtins__.str.str print len(s5) # 3 s6 = "\346\370\345" print "ISO-8859-15 values:" print s6 # זרו -print s6.__class__ # __builtins__.str.string +print s6.__class__ # __builtins__.str.str print len(s6) # 3 s7 = r"\346\370\345" print "Untranslated values:" print s7 # \346\370\345 -print s7.__class__ # __builtins__.unicode.utf8string +print s7.__class__ # __builtins__.unicode.unicode print len(s7) # 12 # Obtain text and print it. @@ -58,7 +58,7 @@ u = unicode(b"זרו", "ISO-8859-15") print "Unicode values:" print u # זרו -print u.__class__ # __builtins__.unicode.utf8string +print u.__class__ # __builtins__.unicode.unicode print u.encode("ISO-8859-15") # זרו print u.encoding # ISO-8859-15 print len(u) # 3 @@ -68,7 +68,7 @@ u2 = u"זרו" print "Unicode values:" print u2 # זרו -print u2.__class__ # __builtins__.unicode.utf8string +print u2.__class__ # __builtins__.unicode.unicode print u2.encode("ISO-8859-15") # זרו print u2.encoding # ISO-8859-15 print len(u2) # 3 @@ -78,7 +78,7 @@ u3 = "זרו" print "Unicode values:" print u3 # זרו -print u3.__class__ # __builtins__.unicode.utf8string +print u3.__class__ # __builtins__.unicode.unicode print u3.encode("ISO-8859-15") # זרו print u3.encoding # ISO-8859-15 print len(u3) # 3 @@ -88,7 +88,7 @@ u4 = unicode("זרו", "ISO-8859-15") print "Unicode values:" print u4 # זרו -print u4.__class__ # __builtins__.unicode.utf8string +print u4.__class__ # __builtins__.unicode.unicode print u4.encode("ISO-8859-15") # זרו print u4.encoding # ISO-8859-15 print len(u4) # 3 @@ -98,7 +98,7 @@ u5 = "\u00e6\u00f8\u00e5" print "Unicode values:" print u5 # זרו -print u5.__class__ # __builtins__.unicode.ut8string +print u5.__class__ # __builtins__.unicode.unicode print len(u5) # 3 # Test some untranslated values. @@ -106,7 +106,7 @@ u6 = "\\u00e6\\u00f8\\u00e5" print "Untranslated values:" print u6 # \u00e6\u00f8\u00e5 -print u6.__class__ # __builtins__.unicode.ut8string +print u6.__class__ # __builtins__.unicode.unicode print len(u6) # 18 # Test Unicode values. @@ -114,7 +114,7 @@ u7 = u"\346\370\345" print "Unicode values:" print u7 # זרו -print u7.__class__ # __builtins__.unicode.ut8string +print u7.__class__ # __builtins__.unicode.unicode print len(u7) # 3 # Test Unicode values. @@ -122,7 +122,7 @@ u8 = ur"\346\370\345" print "Untranslated values:" print u8 # \346\370\345 -print u8.__class__ # __builtins__.unicode.ut8string +print u8.__class__ # __builtins__.unicode.unicode print len(u8) # 12 # Test invalid sequences. @@ -137,7 +137,7 @@ u10 = "\u00e6\xf8\u00e5" print "ISO-8859-15 values:" print u10 # \u00e6ר\u00e5 -print u10.__class__ # __builtins__.str.string +print u10.__class__ # __builtins__.str.str print len(u10) # 13 # Combine bytes and text. @@ -146,7 +146,7 @@ su = s + u print "ISO-8859-15 values:" print su # ֶ״ֵזרו -print su.__class__ # __builtins__.str.string +print su.__class__ # __builtins__.str.str print len(su) # 6 # Combine text and bytes. @@ -155,7 +155,7 @@ us = u + s print "ISO-8859-15 values:" print us # זרוֶ״ֵ -print us.__class__ # __builtins__.str.string +print us.__class__ # __builtins__.str.str print len(us) # 6 # Combine text and text. @@ -163,7 +163,7 @@ uu2 = u + u2 print "Unicode values:" print uu2 # זרוזרו -print uu2.__class__ # __builtins__.unicode.utf8string +print uu2.__class__ # __builtins__.unicode.unicode print uu2.encoding # ISO-8859-15 print len(uu2) # 6 @@ -195,7 +195,7 @@ # Test character access. u0 = u[0] -print u0.__class__ # __builtins__.unicode.utf8string +print u0.__class__ # __builtins__.unicode.unicode print u0.encoding # ISO-8859-15 print u0 # ז print u[-1] # ו