Compare commits

...

10 Commits

Author SHA1 Message Date
235910b863 Be better on startup 2022-06-14 16:28:44 +02:00
33cb150cf0 Be better on startup 2022-06-14 16:25:53 +02:00
66fe79f2bf Fix metacello load order 2022-06-14 16:10:55 +02:00
d75b000ad1 A better IDE 2022-06-14 15:54:07 +02:00
22d00d0360 Add coder 2022-06-14 00:05:36 +02:00
8da76b5a3f Stop carp application on image restart 2022-06-13 22:54:57 +02:00
ee48ec29f0 Add Fn to type signature explainer 2022-06-13 22:22:22 +02:00
6efcea643f better carp bridge 2022-06-13 22:16:23 +02:00
7fbab0e2a0 Finally, an IDE 2022-06-13 22:13:31 +02:00
ee5c032d90 Added build & run, macro expansion, and other actions 2022-06-13 17:26:32 +02:00
45 changed files with 937 additions and 135 deletions

View File

@@ -8,6 +8,7 @@ class CarpProc:
self.proc = diplomat.Diplomat('carp')
self._version_info = None
self.adornment_re = re.compile(".\[33m.*?\[0m")
self.warning_re = re.compile("\[WARNING\] (.*)\n?")
def wait_for_boot(self):
while not self.proc.output():
@@ -23,11 +24,13 @@ class CarpProc:
while self.proc.output() == old_output:
time.sleep(0.5)
res = self.adornment_re.sub("", self.proc.output()[len(old_output):]).strip()
warnings = self.warning_re.findall(res)
res = self.warning_re.sub("", res)
if res.startswith("=> "):
return {'result': 'success', 'value': res[3:]}
return {'result': 'success', 'value': res[3:], 'warnings': warnings}
if not res:
return {'result': 'success', 'value': '()'}
return {'result': 'error', 'value': res}
return {'result': 'success', 'value': '()', 'warnings': warnings}
return {'result': 'error', 'value': res, 'warnings': warnings}
def evaluate(self, statements):
assert self.proc.is_running(), "carp process has died"

View File

@@ -103,14 +103,14 @@
"__type" : "time",
"time" : {
"__type" : "dateAndTime",
"dateAndTimeString" : "2022-04-17T19:36:14.725535+02:00"
"dateAndTimeString" : "2022-06-13T22:57:31.662829+02:00"
}
},
"uid" : {
"__type" : "uid",
"uidString" : "yC3J0D6ZDQCd0ZgmDqn2mw=="
},
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: (CarpCall function: '+' asCarpSymbol arguments: { \r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol }));\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: {}'+' asCarpSymbol arguments: { \r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol }));\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
},
{
"__type" : "textSnippet",
@@ -248,7 +248,7 @@
"__type" : "time",
"time" : {
"__type" : "dateAndTime",
"dateAndTimeString" : "2022-04-17T19:40:10.759445+02:00"
"dateAndTimeString" : "2022-04-17T19:40:21.249005+02:00"
}
},
"uid" : {
@@ -258,7 +258,7 @@
"paragraphStyle" : {
"__type" : "textStyle"
},
"string" : "In the next chapter, we will use this code generator in our newly created coder"
"string" : "In the next chapter named [[A coder of ones own]], we will use this code generator in our newly created coder."
}
]
},

View File

@@ -103,14 +103,14 @@
"__type" : "time",
"time" : {
"__type" : "dateAndTime",
"dateAndTimeString" : "2022-04-17T19:36:14.725535+02:00"
"dateAndTimeString" : "2022-06-13T22:57:42.883096+02:00"
}
},
"uid" : {
"__type" : "uid",
"uidString" : "yC3J0D6ZDQCd0ZgmDqn2mw=="
},
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: (CarpCall function: '+' asCarpSymbol arguments: { \r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol }));\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: {'+' asCarpSymbol .\r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol } asCarpCall);\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
},
{
"__type" : "textSnippet",

View File

@@ -13,6 +13,6 @@ BaselineOfCarp >> baseline: spec [
baseline: 'GToolkit4SmaCC'
with: [ spec repository: 'github://feenkcom/gt4smacc:main/src' ].
spec package: 'Carp' with: [ spec requires: #('GToolkit4SmaCC') ].
spec package: 'Carp-Parser' with: [ spec requires: #('GToolkit4SmaCC') ].
spec package: 'Carp-AST' with: [ spec requires: #('GToolkit4SmaCC') ] ]
spec package: 'Carp-AST' with: [ spec requires: #('GToolkit4SmaCC') ].
spec package: 'Carp-Parser' with: [ spec requires: #('GToolkit4SmaCC') ] ]
]

View File

@@ -13,6 +13,11 @@ CarpCharacterNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitCharacter: self
]
{ #category : #accessing }
CarpCharacterNode >> intoModel [
^ CarpCharacter character: self value source asCharacter
]
{ #category : #accessing }
CarpCharacterNode >> toPharo [
^ value source asCharacter

View File

@@ -16,6 +16,16 @@ CarpExpressionNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitExpression: self
]
{ #category : #accessing }
CarpExpressionNode >> isDefinition [
^ false
]
{ #category : #accessing }
CarpExpressionNode >> isDefinitionPredicate [
^ false
]
{ #category : #accessing }
CarpExpressionNode >> isQuoted [
^ parent ifNil: [ false ] ifNotNil: [ parent isQuoted ]

View File

@@ -13,6 +13,11 @@ CarpNumberNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitNumber: self
]
{ #category : #accessing }
CarpNumberNode >> intoModel [
^ CarpDouble number: self value source asNumber
]
{ #category : #accessing }
CarpNumberNode >> toPharo [
^ value source asInteger

View File

@@ -39,6 +39,12 @@ CarpStartNode >> initialize [
expressions := OrderedCollection new: 2.
]
{ #category : #accessing }
CarpStartNode >> intoModel [
self assert: self expressions size = 1.
^ self expressions first intoModel
]
{ #category : #accessing }
CarpStartNode >> toPharo [
^ expressions collect: #toPharo

View File

@@ -13,6 +13,11 @@ CarpStringNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitString: self
]
{ #category : #accessing }
CarpStringNode >> intoModel [
^ CarpStringExpression contents: self value source
]
{ #category : #accessing }
CarpStringNode >> toPharo [
^ value source

View File

@@ -13,6 +13,20 @@ CarpVariableNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitVariable: self
]
{ #category : #accessing }
CarpVariableNode >> intoModel [
^ CarpSymbol named: self value source
]
{ #category : #accessing }
CarpVariableNode >> isDefinitionPredicate [
^ {'defdynamic'.
'defndynamic'.
'defmacro'.
'defn'.
'def'} includes: self value source
]
{ #category : #accessing }
CarpVariableNode >> toPharo [
^ value source asSymbol

View File

@@ -41,6 +41,11 @@ CarpArrayNode >> initialize [
expressions := OrderedCollection new: 2.
]
{ #category : #accessing }
CarpArrayNode >> intoModel [
^ CarpArray contents: (expressions collect: #intoModel)
]
{ #category : #generated }
CarpArrayNode >> leftBracket [

View File

@@ -26,6 +26,11 @@ CarpDerefNode >> derefGlyph: aSmaCCToken [
derefGlyph := aSmaCCToken
]
{ #category : #accessing }
CarpDerefNode >> intoModel [
^ CarpCall function: 'deref' arguments: {value intoModel}
]
{ #category : #generated }
CarpDerefNode >> nodeVariables [

View File

@@ -21,6 +21,14 @@ CarpListNode >> compositeNodeVariables [
^ #( #expressions )
]
{ #category : #accessing }
CarpListNode >> definitionVariable [
^ (self expressions size > 1
and: [ self expressions first isDefinitionPredicate ])
ifTrue: [ self expressions second ]
ifFalse: [ nil ]
]
{ #category : #generated }
CarpListNode >> expressions [
@@ -41,6 +49,27 @@ CarpListNode >> initialize [
expressions := OrderedCollection new: 2.
]
{ #category : #accessing }
CarpListNode >> intoModel [
^ self isDefinition
ifTrue: [ | binding |
binding := (CarpBinding perform: self expressions first value source asSymbol)
name: self definitionVariable intoModel.
self expressions size = 3
ifTrue: [ binding binding: self expressions third intoModel ].
self expressions size = 4
ifTrue: [ binding
arguments: self expressions third intoModel;
body: self expressions fourth intoModel ].
binding ]
ifFalse: [ CarpList contents: (expressions collect: #intoModel) ]
]
{ #category : #accessing }
CarpListNode >> isDefinition [
^ self definitionVariable isNotNil
]
{ #category : #generated }
CarpListNode >> leftParen [

View File

@@ -27,6 +27,15 @@ CarpMapNode >> initialize [
pairs := OrderedCollection new: 2.
]
{ #category : #accessing }
CarpMapNode >> intoModel [
^ CarpMap
contents: (pairs
flatCollect: [ :p |
{p key intoModel.
p value intoModel} ])
]
{ #category : #generated }
CarpMapNode >> leftBrace [

View File

@@ -14,6 +14,14 @@ CarpModuleOrTypeNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitModuleOrType: self
]
{ #category : #accessing }
CarpModuleOrTypeNode >> intoModel [
^ CarpSymbol
named: ('.'
join: {module source.
value source})
]
{ #category : #generated }
CarpModuleOrTypeNode >> module [

View File

@@ -14,6 +14,11 @@ CarpRefCallNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitRefCall: self
]
{ #category : #accessing }
CarpRefCallNode >> intoModel [
^ CarpCall function: '~' arguments: {value intoModel}
]
{ #category : #generated }
CarpRefCallNode >> nodeVariables [

View File

@@ -14,6 +14,11 @@ CarpRefNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitRef: self
]
{ #category : #accessing }
CarpRefNode >> intoModel [
^ CarpCall function: 'ref' arguments: {value intoModel}
]
{ #category : #generated }
CarpRefNode >> nodeVariables [

View File

@@ -14,6 +14,11 @@ CarpUnquoteNode >> acceptVisitor: anExpressionVisitor [
^ anExpressionVisitor visitUnquote: self
]
{ #category : #accessing }
CarpUnquoteNode >> intoModel [
^ CarpCall function: 'unquote' arguments: {value intoModel}
]
{ #category : #accessing }
CarpUnquoteNode >> isQuoted [
^ false

View File

@@ -13,6 +13,11 @@ CarpApplication class >> start [
^ self startWith: LanguageLinkSettings carpDefaultSettings.
]
{ #category : #'class initialization' }
CarpApplication class >> startUp: resuming [
resuming ifTrue: [ self stop ]
]
{ #category : #accessing }
CarpApplication >> baseApplication [
^ CarpApplication

View File

@@ -0,0 +1,15 @@
Class {
#name : #CarpArray,
#superclass : #CarpSequence,
#category : #'Carp-IDE'
}
{ #category : #accessing }
CarpArray >> close [
^ ']'
]
{ #category : #accessing }
CarpArray >> open [
^ '['
]

View File

@@ -7,6 +7,31 @@ Class {
#category : #'Carp-IDE'
}
{ #category : #'instance creation' }
CarpBinding class >> def [
^ CarpStaticVariable new
]
{ #category : #'instance creation' }
CarpBinding class >> defdynamic [
^ CarpDynamicVariable new
]
{ #category : #'instance creation' }
CarpBinding class >> defmacro [
^ CarpMacro new
]
{ #category : #'instance creation' }
CarpBinding class >> defn [
^ CarpStaticFunction new
]
{ #category : #'instance creation' }
CarpBinding class >> defndynamic [
^ CarpDynamicFunction new
]
{ #category : #accessing }
CarpBinding >> bindingName [
^ self subclassResponsibility

View File

@@ -0,0 +1,28 @@
Class {
#name : #CarpCharacter,
#superclass : #CarpLiteral,
#instVars : [
'character'
],
#category : #'Carp-IDE'
}
{ #category : #'instance creation' }
CarpCharacter class >> character: aCharacter [
^ self new character: aCharacter
]
{ #category : #accessing }
CarpCharacter >> character [
^ character
]
{ #category : #accessing }
CarpCharacter >> character: aCharacter [
character := aCharacter
]
{ #category : #accessing }
CarpCharacter >> toCarp [
^ '\', self character
]

View File

@@ -0,0 +1,51 @@
Class {
#name : #CarpCliOutput,
#superclass : #Object,
#instVars : [
'text'
],
#category : #'Carp-Core'
}
{ #category : #accessing }
CarpCliOutput class >> text: aString [
^ self new text: aString
]
{ #category : #accessing }
CarpCliOutput >> gtExitCodeFor: aView [
<gtView>
^ aView forward
title: 'Exit Code';
priority: 2;
object: [ self text lines last asInteger ];
view: #gtLiveFor:
]
{ #category : #accessing }
CarpCliOutput >> gtOutputFor: aView [
<gtView>
^ aView textEditor
title: 'Output';
priority: 1;
text: [ Character lf join: (self text lines allButLast: 2) ]
]
{ #category : #accessing }
CarpCliOutput >> gtRawOutputFor: aView [
<gtView>
^ aView textEditor
title: 'Raw Output';
priority: 3;
text: [ self text ]
]
{ #category : #accessing }
CarpCliOutput >> text [
^ text
]
{ #category : #accessing }
CarpCliOutput >> text: aString [
text := aString
]

View File

@@ -3,3 +3,8 @@ Class {
#superclass : #CarpNumber,
#category : #'Carp-IDE'
}
{ #category : #accessing }
CarpDouble >> suffix [
^ ''
]

View File

@@ -0,0 +1,68 @@
Class {
#name : #CarpExecutionResult,
#superclass : #Object,
#instVars : [
'value',
'warnings',
'view'
],
#category : #'Carp-Execution'
}
{ #category : #'instance creation' }
CarpExecutionResult class >> from: aCarpResult [
^ self new
value: (aCarpResult at: #value);
warnings: (aCarpResult at: #warnings)
]
{ #category : #accessing }
CarpExecutionResult >> gtValueFor: aView [
<gtView>
| v |
v := aView forward
title: 'Value';
priority: 1;
object: value.
view ifNotNil: [ v view: view ].
^ v
]
{ #category : #accessing }
CarpExecutionResult >> gtWarningsFor: aView [
<gtView>
^ aView list
title: 'Warnings';
priority: 2;
items: [ warnings ]
]
{ #category : #accessing }
CarpExecutionResult >> parse [
value := CarpParser parse: value
]
{ #category : #accessing }
CarpExecutionResult >> transformValue: aBlock [
value := aBlock value: value
]
{ #category : #accessing }
CarpExecutionResult >> value [
^ value
]
{ #category : #accessing }
CarpExecutionResult >> value: aValue [
value := aValue
]
{ #category : #accessing }
CarpExecutionResult >> view: aView [
view := aView
]
{ #category : #accessing }
CarpExecutionResult >> warnings: aCollection [
warnings := aCollection
]

View File

@@ -12,6 +12,17 @@ CarpExpression >> asElement [
^ (GtCarpCoderModel code: self toCarp) asElement
]
{ #category : #accessing }
CarpExpression >> asElementWithModule: aModule [
| applicationStrategy |
applicationStrategy := LeCarpApplicationStrategy new.
^ (GtExpandableSourceCoderElement new
coderViewModel: ((GtCarpIDECoderModel code: self toCarp)
module: aModule;
carpLinkApplicationStrategy: applicationStrategy;
expression: self) asCoderViewModel) collapse
]
{ #category : #accessing }
CarpExpression >> documentation [
^ documentation ifNil: ['']
@@ -22,6 +33,24 @@ CarpExpression >> documentation: aString [
documentation := aString
]
{ #category : #accessing }
CarpExpression >> gtCoderFor: aView [
<gtView>
^ aView explicit
title: 'Code';
priority: 1;
stencil: [ self asElement ]
]
{ #category : #accessing }
CarpExpression >> gtTextFor: aView [
<gtView>
^ aView textEditor
title: 'String';
priority: 2;
text: [ self toCarp ]
]
{ #category : #converting }
CarpExpression >> toCarp [
^ self subclassResponsibility

View File

@@ -0,0 +1,15 @@
Class {
#name : #CarpList,
#superclass : #CarpSequence,
#category : #'Carp-IDE'
}
{ #category : #accessing }
CarpList >> close [
^ ')'
]
{ #category : #accessing }
CarpList >> open [
^ '('
]

15
src/Carp/CarpMap.class.st Normal file
View File

@@ -0,0 +1,15 @@
Class {
#name : #CarpMap,
#superclass : #CarpSequence,
#category : #'Carp-IDE'
}
{ #category : #accessing }
CarpMap >> close [
^ '}'
]
{ #category : #accessing }
CarpMap >> open [
^ '{'
]

View File

@@ -67,8 +67,7 @@ CarpModule >> carpCoderCommentsFor: aView [
{ #category : #coders }
CarpModule >> carpCoderStreamingMethodsFor: aView context: aPhlowContext [
<gtModuleView>
| aMethodsCoder aMethodsCoderViewModel aNewMethodCoderHolder |
| aMethodsCoder aMethodsCoderViewModel aNewMethodCoderHolder coderElement |
aNewMethodCoderHolder := ValueHolder new.
^ aView explicit
@@ -76,46 +75,36 @@ CarpModule >> carpCoderStreamingMethodsFor: aView context: aPhlowContext [
title: 'Methods';
disableAsync;
actionDropdownButtonDo: [ :aDrodownAction |
aDrodownAction dropdown
aDrodownAction dropdown
icon: BrGlamorousVectorIcons add;
tooltip: 'Add new expression';
content: [ :aButton |
tooltip: 'Add new function';
content: [ :aButton |
| aNewMethodCoder aNewMethodCoderViewModel aHandler |
aNewMethodCoderHolder contents
ifNotNil: [ :aContents |
aNewMethodCoderViewModel := aContents ]
ifNil: [
aNewMethodCoder := GtCarpCoderModel new.
ifNotNil: [ :aContents | aNewMethodCoderViewModel := aContents ]
ifNil: [ aNewMethodCoder := GtCarpNewFunctionCoderModel new
module: self;
carpLinkApplicationStrategy: LeCarpApplicationStrategy new;
onSave: [ aButton fireEvent: BrDropdownHideWish new.
coderElement initializeForModule ].
aNewMethodCoderViewModel := aNewMethodCoder asCoderViewModel.
aNewMethodCoderViewModel
withoutHeader;
expanded: true;
focused: true;
moveCursorAtEnd.
aNewMethodCoderHolder contents: aNewMethodCoderViewModel.
aNewMethodCoderViewModel := aNewMethodCoder asCoderViewModel.
aNewMethodCoderViewModel
withoutHeader;
expanded: true;
focused: true;
moveCursorAtEnd.
aHandler := GtPharoNewMethodCodeSavedHandler new
methodsCoderViewModel: aMethodsCoderViewModel;
element: aButton;
methodCoderHolder: aNewMethodCoderHolder.
aNewMethodCoderViewModel weak
when: GtMethodCoderSaved
send: #onAnnouncement:
to: aHandler ].
aNewMethodCoderHolder contents: aNewMethodCoderViewModel ].
(GtExpandedOnlyCoderElement new coderViewModel: aNewMethodCoderViewModel)
hExact: 300;
vFitContent;
background: Color white;
padding: (BlInsets all: 5);
addAptitude: BrGlamorousFocusableShadowAptitude new ];
name: #'button--add-new-expression'];
stencil: [ CarpStreamingMethodsCoderElement forModule: self ]
(GtExpandedOnlyCoderElement new coderViewModel: aNewMethodCoderViewModel)
hExact: 300;
vFitContent;
background: Color white;
padding: (BlInsets all: 5);
addAptitude: BrGlamorousFocusableShadowAptitude new ];
name: #'button--add-new-expression' ];
stencil: [ coderElement := CarpStreamingMethodsCoderElement forModule: self ]
]
{ #category : #coders }
@@ -194,6 +183,11 @@ CarpModule >> name: aString [
name := aString
]
{ #category : #accessing }
CarpModule >> removeExpression: anExpression [
expressions remove: anExpression
]
{ #category : #accessing }
CarpModule >> removeUse: aString [
uses remove: aString

View File

@@ -19,6 +19,15 @@ CarpModuleCoder >> asCoderViewModel [
^ CarpModuleCoderViewModel new coder: self
]
{ #category : #accessing }
CarpModuleCoder >> coderName [
"Return a short textual name of the coder.
For example, class coder would return a class name, package coder returns a package name."
<return: #String>
^ self module name
]
{ #category : #'instance creation' }
CarpModuleCoder >> module [
^ module

View File

@@ -12,6 +12,17 @@ Class {
#category : #'Carp-Coder'
}
{ #category : #accessing }
CarpModuleCoderElement >> build [
| application commandFactory |
application := CarpApplication start.
commandFactory := application newCommandFactory.
^ commandFactory
<< self module toCarp;
sendAndWait
]
{ #category : #accessing }
CarpModuleCoderElement >> buildContentPane [
@@ -91,6 +102,13 @@ CarpModuleCoderElement >> buildModuleLabel [
action: [ :aButton |
aButton phlow spawnObject: self module toCarp ]).
aContainer addChild: (BrButton new
aptitude: BrGlamorousButtonWithIconAptitude;
icon: BrGlamorousVectorIcons refresh;
beSmallSize;
label: 'Build';
action: [ self build ]).
^ aContainer
]
@@ -133,7 +151,8 @@ CarpModuleCoderElement >> coderViewModel: aCarpCoderViewModel [
container ifNotNil: #removeFromParent.
container := self buildContentPane.
self addChildFirst: container
self addChildFirst: container.
self build
]
{ #category : #accessing }

View File

@@ -49,5 +49,5 @@ CarpNamedFunction >> toCarp [
aStream << '(' << self bindingName << ' ' << self name toCarp
<< ' ['.
arguments do: [ :anArgument | aStream << anArgument toCarp << ' ' ].
aStream << '] ' << self body toCarp << ')' ]
aStream ensureNoSpace << '] ' << self body toCarp << ')' ]
]

View File

@@ -0,0 +1,10 @@
Class {
#name : #CarpPattern,
#superclass : #CarpStringExpression,
#category : #'Carp-IDE'
}
{ #category : #accessing }
CarpPattern >> toCarp [
^ '#', super toCarp
]

View File

@@ -19,11 +19,20 @@ CarpPostMortemDebugger >> exception: anException [
exception := anException
]
{ #category : #accessing }
CarpPostMortemDebugger >> findTrace: inputLines [
| lines |
lines := inputLines asOrderedCollection.
[ lines isNotEmpty and: [ (lines first = 'Traceback:') not ] ]
whileTrue: [ lines removeFirst ].
^ lines
]
{ #category : #accessing }
CarpPostMortemDebugger >> initialize [
super initialize.
frameRegex := '(.*)\s+at.+([^:]+)\:(\d+)\:(\d+)\.' asRegexIgnoringCase.
frameRegex := '(.*)\s+at\s+([^:]+)\:(\d+)\:(\d+)\.' asRegexIgnoringCase.
]
{ #category : #accessing }
@@ -40,11 +49,10 @@ CarpPostMortemDebugger >> stackFrameFromLine: aString ordinal: ordinal [
| file line column source |
^ (frameRegex search: aString) ifTrue:
[ file := frameRegex subexpression: 2.
[ source := frameRegex subexpression: 2.
file := frameRegex subexpression: 3.
line := frameRegex subexpression: 4.
column := frameRegex subexpression: 5.
self halt.
CarpPostMortemStackFrame new
ordinal: ordinal;
displayString: aString;
@@ -62,17 +70,28 @@ CarpPostMortemDebugger >> stackFrameFromLine: aString ordinal: ordinal [
CarpPostMortemDebugger >> stackFrames [
"Answer a ordered collection of stack frames.
This is called many times by the debugger, so cache"
| ordinal |
^ stackFrames ifNil:
[ ordinal := 1.
stackFrames := OrderedCollection new.
exception trace lines do: [ :line |
(self stackFrameFromLine: line ordinal: ordinal) ifNotNil: [ :frame |
stackFrames add: frame.
ordinal := ordinal + 1 ] ].
stackFrames ].
^ stackFrames
ifNil: [ ordinal := 1.
stackFrames := OrderedCollection new.
(self findTrace: exception trace lines)
do: [ :line |
(self stackFrameFromLine: line ordinal: ordinal)
ifNotNil: [ :frame |
stackFrames add: frame.
ordinal := ordinal + 1 ] ].
(exception trace lines last beginsWith: '[RUNTIME ERROR]')
ifTrue: [ stackFrames
add: (CarpPostMortemStackFrame new
ordinal: 1;
displayString: exception trace lines last;
exception: exception;
source: exception trace lines last;
file: 'REPL' asFileReference;
line: 0;
column: 0) ].
stackFrames ]
]
{ #category : #accessing }

View File

@@ -14,5 +14,18 @@ CarpPostMortemStackFrame >> source: aString [
{ #category : #accessing }
CarpPostMortemStackFrame >> sourceText [
^ source
| mySource text indexes lineNumber |
file exists
ifTrue: [ mySource := file contents.
lineNumber := line ]
ifFalse: [ ^ source asRopedText
attribute: (BlTextHighlightAttribute paint: BrGlamorousColors errorBackgroundColor)
beNotOverwritableByStyler ].
text := mySource asRopedText.
indexes := mySource gtIndexOfLineNumber: lineNumber.
indexes
ifNotNil: [ (text from: indexes key + column - 1 to: indexes value)
attribute: (BlTextHighlightAttribute paint: BrGlamorousColors errorBackgroundColor)
beNotOverwritableByStyler ].
^ text
]

View File

@@ -9,6 +9,12 @@ CarpPythonProcess class >> program [
^ 'python'
]
{ #category : #accessing }
CarpPythonProcess class >> resolveCarpPath [
"TODO: make more robust"
^ '/usr/bin/python' asFileReference
]
{ #category : #accessing }
CarpPythonProcess >> processArguments [
| args |

View File

@@ -0,0 +1,43 @@
Class {
#name : #CarpSequence,
#superclass : #CarpLiteral,
#instVars : [
'elements',
'contents'
],
#category : #'Carp-IDE'
}
{ #category : #'instance creation' }
CarpSequence class >> contents: aCollection [
^ self new contents: aCollection
]
{ #category : #accessing }
CarpSequence >> close [
^ self subclassResponsibility
]
{ #category : #accessing }
CarpSequence >> contents: aCollection [
contents := aCollection
]
{ #category : #accessing }
CarpSequence >> do: aBlock [
contents do: aBlock
]
{ #category : #accessing }
CarpSequence >> open [
^ self subclassResponsibility
]
{ #category : #accessing }
CarpSequence >> toCarp [
^ String streamContents: [ :aStream |
aStream << self open.
contents do: [ :anArgument | aStream << anArgument toCarp << ' ' ].
aStream ensureNoSpace << self close]
]

View File

@@ -26,7 +26,7 @@ CarpStreamingMethodsCoderElement >> initialize [
itemType: [ :anItemTypeFactory :anItemObject |
anItemObject ];
itemStencil: [ :anItem |
anItem asElement id: GtSourceCoderId ];
(anItem asElementWithModule: module) id: GtSourceCoderId ];
itemsProvider:
(BrListStreamItemsProvider new stream: AsyncEmptyStream new).

View File

@@ -12,6 +12,11 @@ CarpSymbol class >> named: aString [
^ self new name: aString
]
{ #category : #accessing }
CarpSymbol >> name [
^ name
]
{ #category : #accessing }
CarpSymbol >> name: aString [
name := aString

View File

@@ -0,0 +1,199 @@
Class {
#name : #CarpTypeSignature,
#superclass : #Object,
#instVars : [
'signature',
'model',
'tooltipsContainer'
],
#category : #'Carp-Coder'
}
{ #category : #'instance creation' }
CarpTypeSignature class >> on: aValue using: aModel [
^ self new
fromAST: aValue;
model: aModel
]
{ #category : #accessing }
CarpTypeSignature >> elementsList [
| tokens verticalContainer docsRegex |
tokens := signature value source findTokens: ' () []'.
docsRegex := 'Documentation\: (.*)' asRegexIgnoringCase.
verticalContainer := BrVerticalPane new
fitContent;
padding: (BlInsets all: 10).
tokens
do: [ :each |
| res |
res := model bindAndExecuteRaw: '(info ' , each , ')'.
(docsRegex search: (res at: #value))
ifTrue: [ | docs |
docs := docsRegex subexpression: 2.
verticalContainer
addChild: (BrLabel new
aptitude: BrGlamorousLabelAptitude new
+ (GtExplainerExplanationAptitude new explanationModel: each)
+ (BrStyleCommonAptitude new
hovered: [ :aStyle |
aStyle background: BrGlamorousColors textHighlightColor.
aStyle
do: [ tooltipsContainer
text: docs;
visibility: BlVisibility visible ]
after: [ tooltipsContainer
text: '' asRopedText;
visibility: BlVisibility gone ] ]);
geometry: (BlRoundedRectangleGeometry cornerRadius: 4);
text: each;
padding: (BlInsets all: 5)) ] ].
(tokens includes: '<StaticLifetime>')
ifTrue: [ verticalContainer
addChild: (BrLabel new
aptitude: BrGlamorousLabelAptitude new
+ (GtExplainerExplanationAptitude new explanationModel: '<StaticLifetime>')
+ (BrStyleCommonAptitude new
hovered: [ :aStyle |
aStyle background: BrGlamorousColors textHighlightColor.
aStyle
do: [ tooltipsContainer
text: 'is the default static lifetime of values (this lifetime includes the entire program run).';
visibility: BlVisibility visible ]
after: [ tooltipsContainer
text: '' asRopedText;
visibility: BlVisibility gone ] ]);
geometry: (BlRoundedRectangleGeometry cornerRadius: 4);
text: '<StaticLifetime>';
padding: (BlInsets all: 5)) ].
(tokens includes: 'Fn')
ifTrue: [ verticalContainer
addChild: (BrLabel new
aptitude: BrGlamorousLabelAptitude new
+ (GtExplainerExplanationAptitude new explanationModel: 'Fn')
+ (BrStyleCommonAptitude new
hovered: [ :aStyle |
aStyle background: BrGlamorousColors textHighlightColor.
aStyle
do: [ tooltipsContainer
text: 'is the function type and is read: ' asRopedText, '(Fn [<arguments>] <return type> <lifetime>).' asRopedText glamorousCodeFont;
visibility: BlVisibility visible ]
after: [ tooltipsContainer
text: '' asRopedText;
visibility: BlVisibility gone ] ]);
geometry: (BlRoundedRectangleGeometry cornerRadius: 4);
text: 'Fn';
padding: (BlInsets all: 5)) ].
^ verticalContainer asScrollableElement
constraintsDo: [ :c |
c horizontal fitContent.
c vertical matchParent ];
background: Color white;
aptitude: BrShadowAptitude new
]
{ #category : #accessing }
CarpTypeSignature >> explainSignature [
| mainContainer coderElement leftContainer rightContainer rightContainerLabel leftContainerLabel tooltipsTarget coder elementsContainer editor |
mainContainer := BrHorizontalPane new
matchParent;
padding: (BlInsets all: 5).
mainContainer explainer isExplanationHolder: true.
leftContainer := BrVerticalPane new
hFitContent;
vMatchParent;
padding: (BlInsets all: 5);
margin: (BlInsets right: 20).
rightContainer := BrVerticalPane new
matchParent;
padding: (BlInsets all: 5).
tooltipsContainer := BrEditor new
text: '' asRopedText;
padding: (BlInsets all: 10);
margin: (BlInsets
top: 10
right: 0
bottom: 0
left: 0);
constraintsDo: [ :c | c horizontal matchParent ];
visibility: BlVisibility gone;
border: (BlBorder paint: BrGlamorousColors textHighlightColor width: 2);
aptitude: BrShadowAptitude + BrGlamorousEditorAptitude;
vFitContent;
background: BrGlamorousColors textHighlightColor.
tooltipsTarget := BrButton new
constraintsDo: [ :c | c ignoreByLayout ];
size: 0 @ 0;
elevation: (BlRelativeElevation elevation: 10);
geometry: BlCircleGeometry new.
elementsContainer := self elementsList.
leftContainerLabel := BrLabel new
text: ('Type Elements:' asRopedText
glamorousRegularFont;
foreground: Color gray);
aptitude: BrGlamorousLabelAptitude;
hFitContent;
margin: (BlInsets
top: 0
right: 0
bottom: 5
left: 0).
rightContainerLabel := BrLabel new
text: ('Type:' asRopedText
glamorousRegularFont;
foreground: Color gray);
aptitude: BrGlamorousLabelAptitude;
margin: (BlInsets
top: 0
right: 0
bottom: 5
left: 5).
editor := BrEditorElement new
constraintsDo: [ :c |
c horizontal matchParent.
c vertical matchParent ];
editor: (BrTextEditor new text: signature value source asRopedText glamorousCodeFont).
leftContainer addChild: leftContainerLabel.
leftContainer addChild: elementsContainer.
rightContainer addChild: rightContainerLabel.
rightContainer addChild: editor.
rightContainer addChild: tooltipsContainer.
mainContainer addChild: leftContainer.
mainContainer addChild: rightContainer.
^ mainContainer
]
{ #category : #accessing }
CarpTypeSignature >> fromAST: anASTNode [
signature := anASTNode
]
{ #category : #accessing }
CarpTypeSignature >> gtLiveFor: aView [
<gtView>
^ aView explicit
title: 'Signature';
priority: 1;
stencil: [ self explainSignature ]
]
{ #category : #accessing }
CarpTypeSignature >> model: aModel [
model := aModel
]

View File

@@ -4,7 +4,9 @@ Class {
#instVars : [
'pharoBindings',
'carpLinkApplicationStrategy',
'exception'
'exception',
'application',
'commandFactory'
],
#category : #'Carp-Coder'
}
@@ -28,10 +30,12 @@ GtCarpCoderModel >> bindAndExecute: sourceString [
<gtIgnoreConstraint: #GtRBAcceptVisitorCalledFromNonVisitingMethods>
<remoteDebuggerSignal>
| carpSource trimmedSource ast varNames lastStatement application commandFactory res |
| res trimmedSource ast varNames lastStatement carpSource |
trimmedSource := SmaCCString on: sourceString trimRight.
ast := CarpParser parse: trimmedSource. "The variables to be returned are names that are in pharoBindings"
varNames := pharoBindings bindingNames asSet. "Assign the final statement to snippetResult"
varNames := pharoBindings
ifNil: [ Set new ]
ifNotNil: [ pharoBindings bindingNames asSet ]. "Assign the final statement to snippetResult"
lastStatement := ast expressions last.
trimmedSource
insert: '(defdynamic snippetResult '
@@ -41,21 +45,25 @@ GtCarpCoderModel >> bindAndExecute: sourceString [
carpSource := self
sourceFrom: trimmedSource asString
returnedVarNames: varNames.
res := self bindAndExecuteRaw: sourceString.
(res at: #result) = 'success' ifTrue: [ ^ CarpExecutionResult from: res ].
exception := PharoLinkRemoteError new
application: application;
command: commandFactory command;
trace: (res at: #value).
exception signal
]
{ #category : #accessing }
GtCarpCoderModel >> bindAndExecuteRaw: sourceString [
application := carpLinkApplicationStrategy applicationServer.
application isRunning ifFalse: [ application start ].
commandFactory := application newCommandFactory.
res := commandFactory
<< carpSource;
sendAndWait.
(res at: #result) = 'success' ifTrue: [ ^ res at: #value ].
exception := (PharoLinkRemoteError new
application: application;
command: commandFactory command;
trace: (res at: #value)).
exception signal
^ commandFactory
<< sourceString;
sendAndWait
]
{ #category : #accessing }
@@ -77,36 +85,77 @@ GtCarpCoderModel >> exception [
{ #category : #accessing }
GtCarpCoderModel >> initializeAddOns: addOns [
super initializeAddOns: addOns.
addOns addStyler: (GtCoderAstSmaCCParserStyler new smaccStyler: CarpParser gtStyler).
addOns
addMainAction: 'Evaluate' translated
icon: BrGlamorousVectorIcons play
action: [ :aCoderUIModel :anElement |
GtCoderCodeExecutor doIt
coderViewModel: aCoderUIModel;
element: anElement;
execute ]
id: GtSourceCoderDoItActionId.
addOns
addMainAction: 'Inspect' translated
icon: BrGlamorousVectorIcons playinspect
action: [ :aCoderUIModel :anElement |
GtCoderCodeExecutor doItAndGo
coderViewModel: aCoderUIModel;
element: anElement;
execute ]
id: GtSourceCoderDoItAndGoActionId.
addStyler: (GtCoderAstSmaCCParserStyler new smaccStyler: CarpParser gtStyler).
application
ifNotNil: [ addOns
addMainAction: 'Evaluate' translated
icon: BrGlamorousVectorIcons play
action: [ :aCoderUIModel :anElement |
GtCoderCodeExecutor doIt
coderViewModel: aCoderUIModel;
element: anElement;
execute ]
id: GtSourceCoderDoItActionId.
addOns
addMainAction: 'Inspect' translated
icon: BrGlamorousVectorIcons playinspect
action: [ :aCoderUIModel :anElement |
GtCoderCodeExecutor doItAndGo
coderViewModel: aCoderUIModel;
element: anElement;
execute ]
id: GtSourceCoderDoItAndGoActionId.
addOns
addMainAction: 'Expand Macros' translated
icon: BrGlamorousVectorIcons repair
action: [ :aCoderUIModel :anElement |
| source |
source := '(expand ''' , sourceCode currentSourceText value text , ')'.
anElement phlow
spawnObject: ((self bindAndExecute: source) parse view: #gtSourceFor:) ]
id: #'source-coder--macro-expand-action'.
addOns
addMainAction: 'Build and Run' translated
icon: BrGlamorousVectorIcons refresh
action: [ :aCoderUIModel :anElement |
| source |
source := '' , sourceCode currentSourceText value text , '(build) (run)'.
anElement phlow
spawnObject: (CarpCliOutput text: ((self bindAndExecuteRaw: source) at: 'value')) ]
id: #'source-coder--build-and-run-action'.
addOns
addMainAction: 'Infer Type' translated
icon: BrGlamorousVectorIcons inspect
action: [ :aCoderUIModel :anElement | self inspectTypeSpawningOn: anElement phlow ]
id: #'source-coder--type-infer-action' ]
]
{ #category : #accessing }
GtCarpCoderModel >> initializeShortcuts: addOns [
super initializeShortcuts: addOns.
addOns
addShortcut: GtSourceCoderDoItShortcut new;
addShortcut: GtSourceCoderDoItAndInspectShortcut new
application
ifNotNil: [ addOns
addShortcut: GtSourceCoderDoItShortcut new;
addShortcut: GtSourceCoderDoItAndInspectShortcut new ]
]
{ #category : #accessing }
GtCarpCoderModel >> inspectTypeSpawningOn: aPhlow [
| source ast |
source := sourceCode currentSourceText value text.
ast := CarpParser parse: source.
(ast expressions size = 1 and: [ ast expressions first isDefinition ])
ifTrue: [ self bindAndExecute: source asString.
source := ast expressions first definitionVariable value source ].
source := '(def *type-infer-this* ' , source
, ') (defdynamic *type-infer-result* (type *type-infer-this*)) (def *type-infer-this* 0) *type-infer-result*'.
aPhlow spawnObject: ((self bindAndExecute: source) parse transformValue: [:aValue | CarpTypeSignature on: aValue expressions first using: self])
]
{ #category : #accessing }
@@ -121,7 +170,8 @@ GtCarpCoderModel >> pharoBindings: anObject [
{ #category : #accessing }
GtCarpCoderModel >> primitiveEvaluate: aSourceString inContext: aGtSourceCoderEvaluationContext onFailDo: anEvaluationFailBlock [
^ (CarpParser parse: (self bindAndExecute: aSourceString)) expressions first toPharo
^ (self bindAndExecute: aSourceString) parse
transformValue: [ :aValue | aValue expressions first toPharo ]
]
{ #category : #accessing }

View File

@@ -0,0 +1,50 @@
Class {
#name : #GtCarpIDECoderModel,
#superclass : #GtCarpNewFunctionCoderModel,
#instVars : [
'expression'
],
#category : #'Carp-Coder'
}
{ #category : #accessing }
GtCarpIDECoderModel >> collapsedTextPromise [
^ self expression name name , ' : '
, (self bindAndExecute: '(type ' , module name, '.', self expression name name , ')') value
]
{ #category : #accessing }
GtCarpIDECoderModel >> expression [
^ expression
]
{ #category : #accessing }
GtCarpIDECoderModel >> expression: anExpression [
expression := anExpression
]
{ #category : #accessing }
GtCarpIDECoderModel >> initializeAddOns: addOns [
super initializeAddOns: addOns.
addOns
addMainAction: 'Remove' translated
icon: BrGlamorousVectorIcons remove
action: [ :aCoderUIModel :anElement | self remove ]
id: GtMethodCoderSaveActionId
]
{ #category : #accessing }
GtCarpIDECoderModel >> remove [
module removeExpression: self expression.
self bindAndExecute: module toCarp
]
{ #category : #accessing }
GtCarpIDECoderModel >> save [
module removeExpression: expression.
module
addExpression: (CarpParser parse: sourceCode availableSource text) intoModel.
self bindAndExecute: module toCarp.
onSave ifNotNil: [ onSave value ]
]

View File

@@ -0,0 +1,40 @@
Class {
#name : #GtCarpNewFunctionCoderModel,
#superclass : #GtCarpCoderModel,
#instVars : [
'module',
'onSave'
],
#category : #'Carp-Coder'
}
{ #category : #accessing }
GtCarpNewFunctionCoderModel >> initializeAddOns: addOns [
addOns
addStyler: (GtCoderAstSmaCCParserStyler new smaccStyler: CarpParser gtStyler).
addOns
addMainAction: 'Save' translated
icon: BrGlamorousVectorIcons accept
action: [ :aCoderUIModel :anElement | self save ]
id: GtMethodCoderSaveActionId
]
{ #category : #coders }
GtCarpNewFunctionCoderModel >> module: aModule [
module := aModule
]
{ #category : #accessing }
GtCarpNewFunctionCoderModel >> onSave: aBlock [
onSave := aBlock
]
{ #category : #accessing }
GtCarpNewFunctionCoderModel >> save [
| expression |
expression := (CarpParser parse: sourceCode currentSourceText value text) intoModel.
module addExpression: expression.
self bindAndExecute: module toCarp.
onSave ifNotNil: [ onSave value ]
]

View File

@@ -13,9 +13,6 @@ LeCarpApplicationStrategy class >> strategyName [
{ #category : #accessing }
LeCarpApplicationStrategy >> applicationServer [
content database isDatabase ifFalse: [ ^ nil ].
CarpApplication uniqueInstance ifNil:
[ CarpApplication uniqueInstance: (self newCarpApplicationFor: content database) ].
^ CarpApplication uniqueInstance
]
@@ -27,32 +24,5 @@ LeCarpApplicationStrategy >> applicationSettings [
^ CarpApplication isRunning ifTrue:
[ CarpApplication uniqueInstance settings ]
ifFalse:
[ self updatedSettings: CarpApplication defaultSettings ]
]
{ #category : #accessing }
LeCarpApplicationStrategy >> newCarpApplicationFor: aLeDatabase [
^ CarpApplication new initializeWith:
(self updatedSettings: LanguageLinkSettings carpDefaultSettings).
]
{ #category : #accessing }
LeCarpApplicationStrategy >> updatedSettings: applicationCarpSettings [
"Update the supplied settings with the lepiter configuration"
| lepiterCarpSettings lepiterDatabase carpDir |
lepiterDatabase := content database.
(lepiterDatabase isKindOf: LeNullDatabase)
ifTrue: [ ^ applicationCarpSettings ].
lepiterCarpSettings := lepiterDatabase properties carpLinkSettings.
lepiterCarpSettings directory
ifNotNil: [ :relativeDir |
carpDir := lepiterDatabase localStoreRootDirectory resolve: relativeDir.
applicationCarpSettings workingDirectory: carpDir ]. "lepiterCarpSettings carpPath ifNotNil:
[ :carpPath | applicationCarpSettings serverExecutable: carpPath ]."
applicationCarpSettings serverDebugMode: lepiterCarpSettings serverDebugMode.
^ applicationCarpSettings
[ CarpApplication defaultSettings ]
]

View File

@@ -1,11 +1,11 @@
Extension { #name : #ByteString }
Extension { #name : #String }
{ #category : #'*Carp' }
ByteString >> asCarpModule [
String >> asCarpModule [
^ CarpModule named: self
]
{ #category : #'*Carp' }
ByteString >> asCarpSymbol [
String >> asCarpSymbol [
^ CarpSymbol named: self
]