astreum 0.2.4__py3-none-any.whl → 0.2.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of astreum might be problematic. Click here for more details.
- astreum/node.py +1 -1
- {astreum-0.2.4.dist-info → astreum-0.2.6.dist-info}/METADATA +1 -1
- astreum-0.2.6.dist-info/RECORD +18 -0
- astreum/_node/relay/__init__.py +0 -371
- astreum/_node/relay/bucket.py +0 -90
- astreum/_node/relay/envelope.py +0 -280
- astreum/_node/relay/message.py +0 -110
- astreum/_node/relay/peer.py +0 -174
- astreum/_node/relay/route.py +0 -161
- astreum/_node/storage/storage.py +0 -253
- astreum/_node/storage/utils.py +0 -137
- astreum/_node/utils.py +0 -34
- astreum/_node/validation/__init__.py +0 -0
- astreum/_node/validation/_block/__init__.py +0 -0
- astreum/_node/validation/_block/create.py +0 -98
- astreum/_node/validation/_block/model.py +0 -81
- astreum/_node/validation/_block/validate.py +0 -196
- astreum/_node/validation/account.py +0 -99
- astreum/_node/validation/block.py +0 -21
- astreum/_node/validation/constants.py +0 -15
- astreum/_node/validation/stake.py +0 -229
- astreum/_node/validation/transaction.py +0 -146
- astreum/_node/validation/vdf.py +0 -80
- astreum/lispeum/expression.py +0 -95
- astreum/lispeum/special/__init__.py +0 -0
- astreum/lispeum/special/definition.py +0 -27
- astreum/lispeum/special/list/__init__.py +0 -0
- astreum/lispeum/special/list/all.py +0 -32
- astreum/lispeum/special/list/any.py +0 -32
- astreum/lispeum/special/list/fold.py +0 -29
- astreum/lispeum/special/list/get.py +0 -20
- astreum/lispeum/special/list/insert.py +0 -23
- astreum/lispeum/special/list/map.py +0 -30
- astreum/lispeum/special/list/position.py +0 -33
- astreum/lispeum/special/list/remove.py +0 -22
- astreum/lispeum/special/number/__init__.py +0 -0
- astreum/lispeum/special/number/addition.py +0 -0
- astreum/lispeum/storage.py +0 -410
- astreum/machine/__init__.py +0 -352
- astreum/machine/environment.py +0 -4
- astreum/machine/error.py +0 -0
- astreum-0.2.4.dist-info/RECORD +0 -56
- {astreum-0.2.4.dist-info → astreum-0.2.6.dist-info}/WHEEL +0 -0
- {astreum-0.2.4.dist-info → astreum-0.2.6.dist-info}/licenses/LICENSE +0 -0
- {astreum-0.2.4.dist-info → astreum-0.2.6.dist-info}/top_level.txt +0 -0
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
import time
|
|
3
|
-
from .account import Account, get_account_from_storage
|
|
4
|
-
import astreum.format as format
|
|
5
|
-
|
|
6
|
-
class Transaction:
|
|
7
|
-
def __init__(
|
|
8
|
-
self,
|
|
9
|
-
sender: Account,
|
|
10
|
-
recipient: Account,
|
|
11
|
-
amount: int,
|
|
12
|
-
data: bytes = None,
|
|
13
|
-
counter: int = 0
|
|
14
|
-
):
|
|
15
|
-
self.sender = sender
|
|
16
|
-
self.recipient = recipient
|
|
17
|
-
self.amount = amount
|
|
18
|
-
self.data = data
|
|
19
|
-
self.counter = counter
|
|
20
|
-
self.timestamp = time.time()
|
|
21
|
-
self.signature = None
|
|
22
|
-
|
|
23
|
-
@classmethod
|
|
24
|
-
def from_bytes(cls, data: bytes, resolve_accounts: bool = False, accounts=None, storage=None) -> 'Transaction':
|
|
25
|
-
"""
|
|
26
|
-
Deserialize a Transaction from its byte representation.
|
|
27
|
-
|
|
28
|
-
Expected format: [sender_hash, recipient_hash, amount, data, counter, timestamp, signature]
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
data: Serialized transaction data
|
|
32
|
-
resolve_accounts: If True, attempts to resolve account objects from storage
|
|
33
|
-
accounts: Accounts instance (required if resolve_accounts is True)
|
|
34
|
-
storage: Storage instance (required if resolve_accounts is True)
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
Transaction object
|
|
38
|
-
"""
|
|
39
|
-
decoded = format.decode(data)
|
|
40
|
-
sender_public_key, recipient_public_key, amount, tx_data, counter, timestamp, signature = decoded
|
|
41
|
-
|
|
42
|
-
sender_account = None
|
|
43
|
-
recipient_account = None
|
|
44
|
-
|
|
45
|
-
if resolve_accounts:
|
|
46
|
-
if accounts is None or storage is None:
|
|
47
|
-
raise ValueError("Both accounts and storage must be provided when resolve_accounts is True")
|
|
48
|
-
sender_account = get_account_from_storage(sender_public_key, accounts, storage)
|
|
49
|
-
recipient_account = get_account_from_storage(recipient_public_key, accounts, storage)
|
|
50
|
-
else:
|
|
51
|
-
# Create minimal Account objects with just the public keys
|
|
52
|
-
sender_account = Account(sender_public_key, 0, b'', 0, b'')
|
|
53
|
-
recipient_account = Account(recipient_public_key, 0, b'', 0, b'')
|
|
54
|
-
|
|
55
|
-
transaction = cls(sender_account, recipient_account, amount, tx_data, counter)
|
|
56
|
-
transaction.timestamp = timestamp
|
|
57
|
-
transaction.signature = signature
|
|
58
|
-
return transaction
|
|
59
|
-
|
|
60
|
-
def to_bytes(self) -> bytes:
|
|
61
|
-
"""
|
|
62
|
-
Serialize the Transaction into bytes.
|
|
63
|
-
|
|
64
|
-
Format: [sender_hash, recipient_hash, amount, data, counter, timestamp, signature]
|
|
65
|
-
"""
|
|
66
|
-
return format.encode([
|
|
67
|
-
self.sender.public_key,
|
|
68
|
-
self.recipient.public_key,
|
|
69
|
-
self.amount,
|
|
70
|
-
self.data,
|
|
71
|
-
self.counter,
|
|
72
|
-
self.timestamp,
|
|
73
|
-
self.signature
|
|
74
|
-
])
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def get_tx_from_storage(hash: bytes) -> Optional[Transaction]:
|
|
78
|
-
"""Resolves storage objects to get a transaction.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
hash: Hash of the transaction and merkle root of the transaction
|
|
82
|
-
|
|
83
|
-
Returns:
|
|
84
|
-
Transaction object if found, None otherwise
|
|
85
|
-
"""
|
|
86
|
-
return None
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def put_tx_to_storage(transaction: Transaction):
|
|
90
|
-
"""Puts a transaction into storage.
|
|
91
|
-
|
|
92
|
-
Args:
|
|
93
|
-
transaction: Transaction object to put into storage
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
None
|
|
97
|
-
"""
|
|
98
|
-
return None
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def get_tx_hash(transaction: Transaction) -> bytes:
|
|
102
|
-
"""Get the hash of a transaction.
|
|
103
|
-
|
|
104
|
-
Args:
|
|
105
|
-
transaction: Transaction object to get hash for
|
|
106
|
-
|
|
107
|
-
Returns:
|
|
108
|
-
Merkle root of the transaction body hash and signature
|
|
109
|
-
"""
|
|
110
|
-
return hash_data(get_tx_body_hash(transaction) + hash_data(transaction.signature))
|
|
111
|
-
|
|
112
|
-
def get_tx_body_hash(transaction: Transaction) -> bytes:
|
|
113
|
-
"""Get the hash of the transaction body.
|
|
114
|
-
|
|
115
|
-
Args:
|
|
116
|
-
transaction: Transaction object to get hash for
|
|
117
|
-
|
|
118
|
-
Returns:
|
|
119
|
-
Hash of the transaction body
|
|
120
|
-
"""
|
|
121
|
-
return hash_data(transaction)
|
|
122
|
-
|
|
123
|
-
def sign_tx(transaction: Transaction, private_key: bytes) -> Transaction:
|
|
124
|
-
"""Sign a transaction.
|
|
125
|
-
|
|
126
|
-
Args:
|
|
127
|
-
transaction: Transaction object to sign
|
|
128
|
-
private_key: Private key to sign with
|
|
129
|
-
|
|
130
|
-
Returns:
|
|
131
|
-
Signed transaction
|
|
132
|
-
"""
|
|
133
|
-
transaction.signature = hash_data(get_tx_body_hash(transaction) + private_key)
|
|
134
|
-
return transaction
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def verify_tx(transaction: Transaction) -> bool:
|
|
138
|
-
"""Verify a transaction.
|
|
139
|
-
|
|
140
|
-
Args:
|
|
141
|
-
transaction: Transaction object to verify,with sender public key
|
|
142
|
-
|
|
143
|
-
Returns:
|
|
144
|
-
True if the transaction is valid, False otherwise
|
|
145
|
-
"""
|
|
146
|
-
return True
|
astreum/_node/validation/vdf.py
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Verifiable Delay Function (VDF) implementation for Astreum.
|
|
3
|
-
|
|
4
|
-
This module provides functionality for computing and verifying VDFs,
|
|
5
|
-
which are used in the consensus mechanism to create artificial time delays.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import time
|
|
9
|
-
import hashlib
|
|
10
|
-
from typing import Optional
|
|
11
|
-
from .constants import VDF_DIFFICULTY
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def compute_vdf(input_data: bytes, difficulty: Optional[int] = None) -> bytes:
|
|
15
|
-
"""
|
|
16
|
-
Compute VDF output for given input data.
|
|
17
|
-
|
|
18
|
-
Args:
|
|
19
|
-
input_data: Input data for VDF
|
|
20
|
-
difficulty: VDF difficulty level (if None, uses default)
|
|
21
|
-
|
|
22
|
-
Returns:
|
|
23
|
-
VDF output
|
|
24
|
-
"""
|
|
25
|
-
if difficulty is None:
|
|
26
|
-
difficulty = VDF_DIFFICULTY
|
|
27
|
-
|
|
28
|
-
# Simple VDF implementation
|
|
29
|
-
# In a real implementation, this would be a proper VDF algorithm
|
|
30
|
-
# like Wesolowski VDF or Pietrzak VDF
|
|
31
|
-
|
|
32
|
-
# For this implementation, we'll use a simple hash-based time delay
|
|
33
|
-
result = input_data
|
|
34
|
-
for _ in range(difficulty):
|
|
35
|
-
result = hashlib.sha256(result).digest()
|
|
36
|
-
|
|
37
|
-
return result
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def verify_vdf(input_data: bytes, output: bytes, difficulty: Optional[int] = None) -> bool:
|
|
41
|
-
"""
|
|
42
|
-
Verify VDF computation.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
input_data: Input data for VDF
|
|
46
|
-
output: Purported VDF output
|
|
47
|
-
difficulty: VDF difficulty level (if None, uses default)
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
True if output is valid, False otherwise
|
|
51
|
-
"""
|
|
52
|
-
if difficulty is None:
|
|
53
|
-
difficulty = VDF_DIFFICULTY
|
|
54
|
-
|
|
55
|
-
# Compute expected output and compare
|
|
56
|
-
expected = compute_vdf(input_data, difficulty)
|
|
57
|
-
return expected == output
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def validate_block_vdf(block_number: int, previous_hash: bytes, vdf_proof: bytes) -> bool:
|
|
61
|
-
"""
|
|
62
|
-
Validate the VDF proof for a block.
|
|
63
|
-
|
|
64
|
-
Args:
|
|
65
|
-
block_number: Block number
|
|
66
|
-
previous_hash: Hash of previous block
|
|
67
|
-
vdf_proof: VDF proof to validate
|
|
68
|
-
|
|
69
|
-
Returns:
|
|
70
|
-
True if VDF proof is valid, False otherwise
|
|
71
|
-
"""
|
|
72
|
-
# Skip VDF validation for genesis block
|
|
73
|
-
if block_number == 0:
|
|
74
|
-
return True
|
|
75
|
-
|
|
76
|
-
# Compute expected input for the VDF
|
|
77
|
-
vdf_input = previous_hash
|
|
78
|
-
|
|
79
|
-
# Verify the VDF
|
|
80
|
-
return verify_vdf(vdf_input, vdf_proof)
|
astreum/lispeum/expression.py
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
from typing import List, Union
|
|
2
|
-
|
|
3
|
-
class Expr:
|
|
4
|
-
class ListExpr:
|
|
5
|
-
def __init__(self, elements: List['Expr']):
|
|
6
|
-
self.elements = elements
|
|
7
|
-
|
|
8
|
-
def __eq__(self, other):
|
|
9
|
-
if not isinstance(other, Expr.ListExpr):
|
|
10
|
-
return NotImplemented
|
|
11
|
-
return self.elements == other.elements
|
|
12
|
-
|
|
13
|
-
def __ne__(self, other):
|
|
14
|
-
return not self.__eq__(other)
|
|
15
|
-
|
|
16
|
-
@property
|
|
17
|
-
def value(self):
|
|
18
|
-
inner = " ".join(str(e) for e in self.elements)
|
|
19
|
-
return f"({inner})"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def __repr__(self):
|
|
23
|
-
if not self.elements:
|
|
24
|
-
return "()"
|
|
25
|
-
|
|
26
|
-
inner = " ".join(str(e) for e in self.elements)
|
|
27
|
-
return f"({inner})"
|
|
28
|
-
|
|
29
|
-
def __iter__(self):
|
|
30
|
-
return iter(self.elements)
|
|
31
|
-
|
|
32
|
-
def __getitem__(self, index: Union[int, slice]):
|
|
33
|
-
return self.elements[index]
|
|
34
|
-
|
|
35
|
-
def __len__(self):
|
|
36
|
-
return len(self.elements)
|
|
37
|
-
|
|
38
|
-
class Symbol:
|
|
39
|
-
def __init__(self, value: str):
|
|
40
|
-
self.value = value
|
|
41
|
-
|
|
42
|
-
def __repr__(self):
|
|
43
|
-
return self.value
|
|
44
|
-
|
|
45
|
-
class Integer:
|
|
46
|
-
def __init__(self, value: int):
|
|
47
|
-
self.value = value
|
|
48
|
-
|
|
49
|
-
def __repr__(self):
|
|
50
|
-
return str(self.value)
|
|
51
|
-
|
|
52
|
-
class String:
|
|
53
|
-
def __init__(self, value: str):
|
|
54
|
-
self.value = value
|
|
55
|
-
|
|
56
|
-
def __repr__(self):
|
|
57
|
-
return f'"{self.value}"'
|
|
58
|
-
|
|
59
|
-
class Boolean:
|
|
60
|
-
def __init__(self, value: bool):
|
|
61
|
-
self.value = value
|
|
62
|
-
|
|
63
|
-
def __repr__(self):
|
|
64
|
-
return "true" if self.value else "false"
|
|
65
|
-
|
|
66
|
-
class Function:
|
|
67
|
-
def __init__(self, params: List[str], body: 'Expr'):
|
|
68
|
-
self.params = params
|
|
69
|
-
self.body = body
|
|
70
|
-
|
|
71
|
-
def __repr__(self):
|
|
72
|
-
params_str = " ".join(self.params)
|
|
73
|
-
body_str = str(self.body)
|
|
74
|
-
return f"(fn ({params_str}) {body_str})"
|
|
75
|
-
|
|
76
|
-
class Error:
|
|
77
|
-
"""
|
|
78
|
-
Represents an error with a freeform category and message.
|
|
79
|
-
- `category`: A string identifying the type of error (e.g., 'SyntaxError').
|
|
80
|
-
- `message`: A human-readable description of the error.
|
|
81
|
-
- `details`: Optional, additional information about the error.
|
|
82
|
-
"""
|
|
83
|
-
def __init__(self, category: str, message: str, details: str = None):
|
|
84
|
-
if not category:
|
|
85
|
-
raise ValueError("Error category must be provided.")
|
|
86
|
-
if not message:
|
|
87
|
-
raise ValueError("Error message must be provided.")
|
|
88
|
-
self.category = category
|
|
89
|
-
self.message = message
|
|
90
|
-
self.details = details
|
|
91
|
-
|
|
92
|
-
def __repr__(self):
|
|
93
|
-
if self.details:
|
|
94
|
-
return f'({self.category} "{self.message}" {self.details})'
|
|
95
|
-
return f'({self.category} "{self.message}")'
|
|
File without changes
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
from astreum.machine.environment import Environment
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def handle_definition(machine, args: Expr.ListExpr, env: Environment) -> Expr:
|
|
6
|
-
if len(args) != 2:
|
|
7
|
-
return Expr.Error(
|
|
8
|
-
category="SyntaxError",
|
|
9
|
-
message="def expects exactly two arguments: a symbol and an expression"
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
if not isinstance(args[0], Expr.Symbol):
|
|
13
|
-
return Expr.Error(
|
|
14
|
-
category="TypeError",
|
|
15
|
-
message="First argument to def must be a symbol"
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
var_name = args[0].value
|
|
19
|
-
|
|
20
|
-
result = machine.evaluate_expression(args[1], env)
|
|
21
|
-
|
|
22
|
-
if isinstance(result, Expr.Error):
|
|
23
|
-
return result
|
|
24
|
-
|
|
25
|
-
env.set(var_name, result)
|
|
26
|
-
|
|
27
|
-
return result
|
|
File without changes
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
from astreum.machine.environment import Environment
|
|
3
|
-
|
|
4
|
-
def handle_list_all(machine, list: Expr.ListExpr, predicate: Expr.Function, env: Environment) -> Expr:
|
|
5
|
-
if not isinstance(list, Expr.ListExpr):
|
|
6
|
-
return Expr.ListExpr([
|
|
7
|
-
Expr.ListExpr([]),
|
|
8
|
-
Expr.String("First argument must be a list")
|
|
9
|
-
])
|
|
10
|
-
|
|
11
|
-
if not isinstance(predicate, Expr.Function):
|
|
12
|
-
return Expr.ListExpr([
|
|
13
|
-
Expr.ListExpr([]),
|
|
14
|
-
Expr.String("Second argument must be a function")
|
|
15
|
-
])
|
|
16
|
-
|
|
17
|
-
for elem in list.elements:
|
|
18
|
-
new_env = Environment(parent=env)
|
|
19
|
-
new_env.set(predicate.params[0], elem)
|
|
20
|
-
|
|
21
|
-
result, _ = machine.evaluate_expression(predicate, new_env)
|
|
22
|
-
|
|
23
|
-
if result == Expr.Boolean(False):
|
|
24
|
-
return Expr.ListExpr([
|
|
25
|
-
Expr.Boolean(False),
|
|
26
|
-
Expr.ListExpr([])
|
|
27
|
-
])
|
|
28
|
-
|
|
29
|
-
return Expr.ListExpr([
|
|
30
|
-
Expr.Boolean(True),
|
|
31
|
-
Expr.ListExpr([])
|
|
32
|
-
])
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
from astreum.machine.environment import Environment
|
|
3
|
-
|
|
4
|
-
def handle_list_any(machine, list: Expr.ListExpr, predicate: Expr.Function, env: Environment) -> Expr:
|
|
5
|
-
if not isinstance(list, Expr.ListExpr):
|
|
6
|
-
return Expr.ListExpr([
|
|
7
|
-
Expr.ListExpr([]),
|
|
8
|
-
Expr.String("First argument must be a list")
|
|
9
|
-
])
|
|
10
|
-
|
|
11
|
-
if not isinstance(predicate, Expr.Function):
|
|
12
|
-
return Expr.ListExpr([
|
|
13
|
-
Expr.ListExpr([]),
|
|
14
|
-
Expr.String("Second argument must be a function")
|
|
15
|
-
])
|
|
16
|
-
|
|
17
|
-
for elem in list.elements:
|
|
18
|
-
new_env = Environment(parent=env)
|
|
19
|
-
new_env.set(predicate.params[0], elem)
|
|
20
|
-
|
|
21
|
-
result, _ = machine.evaluate_expression(predicate, new_env)
|
|
22
|
-
|
|
23
|
-
if result == Expr.Boolean(True):
|
|
24
|
-
return Expr.ListExpr([
|
|
25
|
-
Expr.Boolean(True),
|
|
26
|
-
Expr.ListExpr([])
|
|
27
|
-
])
|
|
28
|
-
|
|
29
|
-
return Expr.ListExpr([
|
|
30
|
-
Expr.Boolean(False),
|
|
31
|
-
Expr.ListExpr([])
|
|
32
|
-
])
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
from astreum.machine.environment import Environment
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def handle_list_fold(machine, list: Expr.ListExpr, initial: Expr, func: Expr.Function, env: Environment) -> Expr:
|
|
6
|
-
if not isinstance(list, Expr.ListExpr):
|
|
7
|
-
return Expr.ListExpr([
|
|
8
|
-
Expr.ListExpr([]),
|
|
9
|
-
Expr.String("First argument must be a list")
|
|
10
|
-
])
|
|
11
|
-
|
|
12
|
-
if not isinstance(func, Expr.Function):
|
|
13
|
-
return Expr.ListExpr([
|
|
14
|
-
Expr.ListExpr([]),
|
|
15
|
-
Expr.String("Third argument must be a function")
|
|
16
|
-
])
|
|
17
|
-
|
|
18
|
-
result = initial
|
|
19
|
-
for elem in list.elements:
|
|
20
|
-
new_env = Environment(parent=env)
|
|
21
|
-
new_env.set(func.params[0], result)
|
|
22
|
-
new_env.set(func.params[1], elem)
|
|
23
|
-
|
|
24
|
-
result = machine.evaluate_expression(func, new_env)
|
|
25
|
-
|
|
26
|
-
return Expr.ListExpr([
|
|
27
|
-
result,
|
|
28
|
-
Expr.ListExpr([])
|
|
29
|
-
])
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
from astreum.lispeum.expression import Expr
|
|
4
|
-
from astreum.machine.environment import Environment
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def handle_list_get(machine, list: Expr.ListExpr, index: Expr.Integer, env: Environment) -> Expr:
|
|
8
|
-
if not isinstance(list, Expr.ListExpr):
|
|
9
|
-
return Expr.ListExpr([
|
|
10
|
-
Expr.ListExpr([]),
|
|
11
|
-
Expr.String("First argument must be a list")
|
|
12
|
-
])
|
|
13
|
-
|
|
14
|
-
if index.value < 0 or index.value >= len(list.elements):
|
|
15
|
-
return Expr.ListExpr([
|
|
16
|
-
Expr.ListExpr([]),
|
|
17
|
-
Expr.String("Index out of bounds")
|
|
18
|
-
])
|
|
19
|
-
|
|
20
|
-
return machine.evaluate_expression(list.elements[index])
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def handle_list_insert(list: Expr.ListExpr, index: Expr.Integer, value: Expr) -> Expr:
|
|
5
|
-
if not isinstance(list, Expr.ListExpr):
|
|
6
|
-
return Expr.ListExpr([
|
|
7
|
-
Expr.ListExpr([]),
|
|
8
|
-
Expr.String("First argument must be a list")
|
|
9
|
-
])
|
|
10
|
-
|
|
11
|
-
if index.value < 0 or index.value > len(list.elements):
|
|
12
|
-
return Expr.ListExpr([
|
|
13
|
-
Expr.ListExpr([]),
|
|
14
|
-
Expr.String("Index out of bounds")
|
|
15
|
-
])
|
|
16
|
-
|
|
17
|
-
new_elements = list.elements[:index.value] + [value] + list.elements[index.value:]
|
|
18
|
-
|
|
19
|
-
return Expr.ListExpr([
|
|
20
|
-
Expr.ListExpr(new_elements),
|
|
21
|
-
Expr.ListExpr([])
|
|
22
|
-
])
|
|
23
|
-
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
from astreum.machine.environment import Environment
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def handle_list_map(machine, list: Expr.ListExpr, func: Expr.Function, env: Environment) -> Expr:
|
|
6
|
-
if not isinstance(list, Expr.ListExpr):
|
|
7
|
-
return Expr.ListExpr([
|
|
8
|
-
Expr.ListExpr([]),
|
|
9
|
-
Expr.String("First argument must be a list")
|
|
10
|
-
])
|
|
11
|
-
|
|
12
|
-
if not isinstance(func, Expr.Function):
|
|
13
|
-
return Expr.ListExpr([
|
|
14
|
-
Expr.ListExpr([]),
|
|
15
|
-
Expr.String("Second argument must be a function")
|
|
16
|
-
])
|
|
17
|
-
|
|
18
|
-
mapped_elements = []
|
|
19
|
-
for elem in list.elements:
|
|
20
|
-
new_env = Environment(parent=env)
|
|
21
|
-
new_env.set(func.params[0], elem)
|
|
22
|
-
|
|
23
|
-
mapped_elem = machine.evaluate_expression(func.body, new_env)
|
|
24
|
-
|
|
25
|
-
mapped_elements.append(mapped_elem)
|
|
26
|
-
|
|
27
|
-
return Expr.ListExpr([
|
|
28
|
-
Expr.ListExpr(mapped_elements),
|
|
29
|
-
Expr.ListExpr([])
|
|
30
|
-
])
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
from astreum.machine.environment import Environment
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def handle_list_position(machine, list: Expr.ListExpr, predicate: Expr.Function, env: Environment) -> Expr:
|
|
6
|
-
if not isinstance(list, Expr.ListExpr):
|
|
7
|
-
return Expr.ListExpr([
|
|
8
|
-
Expr.ListExpr([]),
|
|
9
|
-
Expr.String("First argument must be a list")
|
|
10
|
-
])
|
|
11
|
-
|
|
12
|
-
if not isinstance(predicate, Expr.Function):
|
|
13
|
-
return Expr.ListExpr([
|
|
14
|
-
Expr.ListExpr([]),
|
|
15
|
-
Expr.String("Second argument must be a function")
|
|
16
|
-
])
|
|
17
|
-
|
|
18
|
-
for idx, elem in enumerate(list.elements):
|
|
19
|
-
new_env = Environment(parent=env)
|
|
20
|
-
new_env.set(predicate.params[0], elem)
|
|
21
|
-
|
|
22
|
-
result, _ = machine.evaluate_expression(predicate, new_env)
|
|
23
|
-
|
|
24
|
-
if result == Expr.Boolean(True):
|
|
25
|
-
return Expr.ListExpr([
|
|
26
|
-
Expr.Integer(idx),
|
|
27
|
-
Expr.ListExpr([])
|
|
28
|
-
])
|
|
29
|
-
|
|
30
|
-
return Expr.ListExpr([
|
|
31
|
-
Expr.ListExpr([]),
|
|
32
|
-
Expr.ListExpr([])
|
|
33
|
-
])
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from astreum.lispeum.expression import Expr
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def handle_list_remove(list: Expr.ListExpr, index: Expr.Integer) -> Expr:
|
|
5
|
-
if not isinstance(list, Expr.ListExpr):
|
|
6
|
-
return Expr.ListExpr([
|
|
7
|
-
Expr.ListExpr([]),
|
|
8
|
-
Expr.String("First argument must be a list")
|
|
9
|
-
])
|
|
10
|
-
|
|
11
|
-
if index.value < 0 or index.value >= len(list.elements):
|
|
12
|
-
return Expr.ListExpr([
|
|
13
|
-
Expr.ListExpr([]),
|
|
14
|
-
Expr.String("Index out of bounds")
|
|
15
|
-
])
|
|
16
|
-
|
|
17
|
-
new_elements = list.elements[:index.value] + list.elements[index.value + 1:]
|
|
18
|
-
|
|
19
|
-
return Expr.ListExpr([
|
|
20
|
-
Expr.ListExpr(new_elements),
|
|
21
|
-
Expr.ListExpr([])
|
|
22
|
-
])
|
|
File without changes
|
|
File without changes
|