-
Notifications
You must be signed in to change notification settings - Fork 68
/
SpurBootstrapNewspeakFilePatcher.class.st
118 lines (106 loc) · 4.21 KB
/
SpurBootstrapNewspeakFilePatcher.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
Class {
#name : #SpurBootstrapNewspeakFilePatcher,
#superclass : #Object,
#instVars : [
'source',
'substitutions'
],
#category : #'CogAttic-Bootstrapping'
}
{ #category : #patching }
SpurBootstrapNewspeakFilePatcher >> editTo: dest [ "<FileStream>"
source reopen.
[substitutions do:
[:tuple|
[:start :end :substitution|
[source position + 1 < start] whileTrue:
[dest nextPut: source next].
dest nextPutAll: (substitution
copyReplaceAll: (String with: Character cr)
with: (String with: Character lf)).
source skip: end - start + 1] valueWithArguments: tuple].
dest nextPutAll: source upToEnd]
ensure: [source close]
]
{ #category : #parsing }
SpurBootstrapNewspeakFilePatcher >> findClassDeclarationFor: className in: ast [ "<ClassDeclarationAST>" "^(ClassDeclarationAST|nil)"
^ast instanceSide nestedClasses
detect: [:classDecl| classDecl name = className]
ifNone: []
]
{ #category : #parsing }
SpurBootstrapNewspeakFilePatcher >> findMethodDeclarationFor: selector "<Symbol>" in: ast [ "<ClassDeclarationAST>" "^(MethodAST|nil)"
ast instanceSide categories do:
[:categoryAST|
categoryAST methods do:
[:methodAST|
methodAST pattern selector = selector ifTrue:
[^methodAST]]].
^nil
]
{ #category : #'initialize-release' }
SpurBootstrapNewspeakFilePatcher >> initialize [
substitutions := SortedCollection sortBlock: [:tupleA :tupleB | tupleA first <= tupleB first]
]
{ #category : #patching }
SpurBootstrapNewspeakFilePatcher >> newspeakSourceFor: method "<CompiledMethod>" selector: selector [ "<Symbol>"
| source startIndex nextIndex |
source := method getSourceFromFile asString allButFirst: method selector size - selector size.
source first ~= selector first ifTrue:
[source replaceFrom: 1 to: selector size with: selector startingAt: 1].
"map comments to Newspeak format..."
startIndex := 1.
[(startIndex := source indexOf: $" startingAt: startIndex) > 0] whileTrue:
[nextIndex := source indexOf: $" startingAt: startIndex + 1.
nextIndex < startIndex ifTrue:
[self error: 'matching close comment not found'].
source := source copyReplaceFrom: nextIndex to: nextIndex with: ' *)'.
source := source copyReplaceFrom: startIndex to: startIndex with: '(* '.
startIndex := nextIndex + 5].
"map assignments to Newspeak format"
startIndex := 1.
[(startIndex := source indexOfSubCollection: ':=' startingAt: startIndex) > 0] whileTrue:
[nextIndex := startIndex.
[(source at: nextIndex - 1) isSeparator] whileTrue:
[nextIndex := nextIndex - 1].
source := source copyReplaceFrom: nextIndex to: startIndex + 1 with: '::'.
startIndex := nextIndex + 1].
"add the horror-show parentheses"
startIndex := source indexOf: Character cr.
source := source copyReplaceFrom: startIndex to: startIndex - 1 with: ' = ('.
source := source, (String with: Character cr with: $) ).
^source
]
{ #category : #parsing }
SpurBootstrapNewspeakFilePatcher >> parse [
| platform |
platform := BlackMarket platform.
^[(NewspeakParsing
usingPlatform: platform
grammar: (NewspeakGrammar parserLib: (CombinatorialParsing usingPlatform: platform))
asts: (NewspeakASTs usingLib: platform)) Parser new compilationUnit parse: source]
ensure: [source close]
]
{ #category : #patching }
SpurBootstrapNewspeakFilePatcher >> patch: className inDirectory: dir [
"SpurBootstrapNewspeakFilePatcher new
patch: 'KernelForSqueak'
inDirectory: '../newspeak'"
| directory |
directory := FileDirectory default directoryNamed: dir.
source := directory oldFileNamed: className, '.ns3'.
self substitute: self parse.
self editTo: (directory forceNewFileNamed: className, '.ns3.patched')
]
{ #category : #patching }
SpurBootstrapNewspeakFilePatcher >> substitute: ast [ "<ClassDeclarationAST>"
SpurBootstrap new prototypeClassNameMetaSelectorMethodDo:
[:className :isMeta :selector :method| | source |
method primitive = 0 ifTrue: "all primitives are in the VMMirror package"
[(self findClassDeclarationFor: className in: ast) ifNotNil:
[:classDecl|
(self findMethodDeclarationFor: selector in: classDecl) ifNotNil:
[:methodDecl|
source := self newspeakSourceFor: method selector: selector.
substitutions add: {methodDecl start. methodDecl end. source}]]]]
]