Pull to refresh
54
0
Евгений Головин@evgeniyup

User

Send message
Я напишу отдельную статью про оценку производительности.
1. Логику нужно скриптовать на OS, работать со стеком может понадобиться при прикручивании к OS пользовательской библиотеки.
2. Исключения в виде try catch пока не реализованы, но это планируется ввести при необходимости. Сейчас есть triggerError и возможность обработки ошибок на OS или C++, например, деление на 0 кидает ошибку, которую можно перехватить.
3. замыкания реализованы, без них не было бы никакого смысла
Это будет в одной из следующих статей.
Пример: вызовем функцию concat с двумя параметрами и получим результат в C++:

os->getGlobal("concat");    // добавляем в стек глобальную функцию concat
os->pushNull();             // добавляем this для функции concat
os->pushNumber(5);          // первый параметр для concat
os->pushString(" big differences"); // второй параметр для concat
os->call(2, 1);             // вызываем функцию concat с 2 параметрами, затребуем 1 результат
OS::String res = os->popString(); // сохраним результат в виде строки и уберем его из стека

OS API реализует целый ряд функций для преобразования значений в стеке в простые типы, например, toFloat, toDouble, toInt, toString, toUserdata, popFloat, popBool и т.д.

Пример функции, которую я использую для преобразования объекта {x=10 y=20} в стеке по смещению offs в b2Vec2 (это из интеграции с Box2d):

static b2Vec2 to(OS * os, int offs)
{
	if(os->isObject(offs)){
		os->getProperty(offs, "x"); // required
		float x = os->popNumber();
	
		os->getProperty(offs, "y"); // required
		float y = os->popNumber();

		return b2Vec2(x, y);
	}
	os->triggerError(OS_E_ERROR, "point expected");
	return b2Vec2(0, 0);
}
Скриптование игровой и программной логики, кросс переносимость между разными платформами. Как известно, во многих играх используется Lua для написания UI и т.п. OS нацелен на аналогичные задачи, все то, что решает Lua и JS в качестве скриптовых языков, можно делать на OS, но в более удобной форме. Я, например, занимаюсь разработкой кросс платформенного мобильного движка на OS. Не исключаю эффективное использование OS на веб серверах, т.е. на задачах, которые сейчас решает PHP и node-js.
Я вижу следующие причины по которым язык реализован как есть:

  • все функции в языке — это реально лямбда функции, т.е. по умолчанию они не принадлежат объекту
  • функции в протопите объекта могут быть перезаписаны позже, например, для расширения функционала
  • любую функцию всегда можно вызвать с нужным this и для любого объекта
  • объект всегда совместим с JSON данными

Но в то же время, любые разумные предложения приветствуются, предложения и способы реализации.
Важно понимать, что цели заменить С++ или другой подобный язык не было. JavaScript — замечательный язык программирования. Но после разработки на нем нескольких больших проектов, мне крайне стало не хватать более человеческого ООП. Когда в очередном мобильном проекте в очередной раз пришлось нагараживать пятиэтажные конструкции и писать кучу кода на C++ вместо одной строчки на JS-подобном языке, я все таки собрался и сделал ObjectScript, сделал для своих проектов, ну а в процессе уже решил выложить в паблик. При этом тянуть на с свои проекты V8 с теми недостатками JS, кот. я перечислил выше, Lua фактически с теми же недостатками или др. язык я просто не стал по идеологическим соображениям. Сделал ObjectScript, чтобы писать для мобильных платформ. Если вам кажется, что OS похож на JS, то правильно кажется, у них и названия похожи. Я планировал сохранить все, что есть в JS и добавить при этом то, чего не хватало.
не совсем, typeof возвращает тип аргумента в виде строки, а именно одно из: number, string, boolean, null, array, object, function, userdata.

Простые типы это: number, string, boolean, null. Оператор valueof преобразует аргумент в простой тип.

Но на практике часто используются др. сопутствующие операторы, например, numberof и т.п., например:

function setOptions(options){
  options = objectof options || {}
  ....
}

в JavasScript часто пишут так:

function setOptions(options){
  options = options || {}
  ....
}

что полностью допустимо в ObjectScript, а в сочетании с objectof дополнительная проверка типа.
преобразует значение в простой тип данных, я расскажу об этом и др. специальных операторах в следующей статье
Согласен. Продолжение статьи…

Инкапсуляции

Класс IvanPerson не знает, как реализован метод walk() из класса Person, но может использовать этот метод. В классе IvanPerson нет необходимости даже определять walk() до тех пор, пока не понадобиться изменить его. Все классы наследуют методы своих родителей и определяют только новые методы или те, которые нужно изменить — это называется инкапсуляция.

Перегрузка методов

Опишем класс IvanPerson следующим образом
	var IvanPerson = extends Person {
		__construct = function(){
			super("Ivan", "Petrov")
		}
		walk = function(){
			echo "Soneone named "
			super()
		}
	}
	var p = IvanPerson() // создадим экземпляр класса IvanPerson
	p.walk()
	print p

Выведется:

Soneone named Ivan Petrov is walking!
{"firstname":"Ivan","lastname":"Petrov"}


super вызывает метод родительского класса (прототипа) с именем метода, из которого он был вызван! Тут речь идет о любом методе, нужно просто вызвать super с нужными параметрами.

Ручная передача this в функцию

Чтобы вызвать функцию и передать в нее нужный нам this, воспользуйтесь методом call класса Function. Продолжая предыдущий пример:

	Person.walk.call(p)

Выведется:

Ivan Petrov is walking!

Метод call вызывает функцию с нужным нам this и остальными параметрами, с которыми call был вызван. Если остальные параметры собраны в масив, то воспользуйтесь методом apply класса Function.

	function foo(a, b){ return a + b }
	function bar(){ return foo.apply(null, arguments) }
	print bar(2 3)
	print bar(4 5)

Выведется:

5
9


P.S. заодно проверил и исправил баг в apply, если вы уже клонировали репозиторй, обновитесь пожалуйста
Первый пример с Box2d кстати готов, можно посмотреть видео тут youtu.be/3RHek-UhkCk, как это работает — видимо это тоже тема для новых статей.
да user_param, но вопрос очень интересный и требует описания, видимо это тема для отдельной статьи
В начале я планировал использовать ref-counting + GC для решения проблем с cyclic references, но в ходе реализации сборщика мусора ref-counting как таковой был убран, т.к. ничего не упрощал в процессе сбора мусора. В текущей реализации ref-count присутствует, но только как счетчик использования объекта где-то на стороне (за пределами OS) и зовется в коде external_ref_count. Иначе говоря сам OS ref-count не использует, а сборщик мусора не удаляет объекты с external_ref_count > 0. Cyclic references при этом разруливается без проблем.
Я попробовал реализовать tri-color incremental garbage collector, иначе говоря сборка мусора делается не за один проход, а за много во избежании высокой нагрузки самого сборщика на систему. Что из этого получилось? Работает и не падает, все что надо удаляет, удалось затюнить сборщик для максимально возможного fps на моем мобильнике HTC Desire (в тех демках, что я делаю на OS). Тем не менее, я не доволен тем, что fps не ровный, но пока не уверен в чем именно проблема, в сборщике мусора или в чем-то другом.
Изначально язык нацелен на аудиторию лояльную к C-подобным языкам, к ним я отношу JavaScript, PHP, Lua ну и некоторые другие.

А в целом я работаю над реализацией движка для написания кросс платформенных приложений по типу Corona SDK, но на ObjectScript и Marmalade SDK. Не отказался бы от интеграции с др. платформами, например, Irrlicht, Shiva3D и др. В принципе область применения может быть довольно большой, тот же node.os (как аналог node.js).

Насколько мне известно, от русскоязычного комьюнити мировому сообществу пока не предложено языков высокого уровня. Что я предлагаю — завершить спецификацию ObjectScript, создать комьюнити, может быть найти инвестиции.
Сейчас я подключаю Box2d, видимо скоро покажу демку. OS изначально был ориентирован на простую интеграцию с C++
Будет синтаксическая ошибка, попытается вернуть b, а там равно, равно в OS не возвращает значение. По крайней мере в текущей версии, тут прямой аналог — Lua, и нужно это для множественного присваивания, когда значение вынимается из стека, чтобы корректно присвоить следующее значение. Поэтому после return следует ставить ; чтобы однозначно отделить синтаксис.
1. в Lua работают и запятые и точки с запятой, тут я не усмотрел криминала, хотя и соглашусь с тем, что лучше использовать один синтаксис

2. согласен

3. дело в том, что
	a = {x=1, y=3; "zero" "one", "two" last:7,}

эквивалентен объекту на JS
	a = {x:1, y:3, 0:"zero", 1:"one", 2:"two", last:7}

поэтому print a[1] выведет one

4. в OS (ObjectScript) изначально все функции — лямбды, запись с ключевым словом function на мой взгляд воспринимается более читабельно

5. код obj = { null awesome={1,2} {12, 24}} for({k, v} in obj){ print( k " --> " v ) } не совсем валидный в части for({k, v}, тут требуется writeable, а {k, v} не writeable и компилятор будет ругаться

6. 7. согласен get color { return .... } выглядит лучше. Я хочу лишь отметить, что это все равно будет скомпилировано в метод с именем __get@color, а это нужно программисту теоретически знать. Сейчас уже есть синтаксис вида:
var alphaBlending
function get alphaBlending(){ return alphaBlending }
function set alphaBlending(a){
	alphaBlending = a
	if(a){
		glEnable(GL_BLEND)
		glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST)
	}else{
		glDisable(GL_BLEND)
	}
}

см. director.os — это из 2d движка, который я пишу для мобильных платформ на ObjectScript. Данный синтаксис пока не добавлен в описание объекта.

8. delete работает также как в JS, т.е. удаляется не само значение, а ссылка на него или свойство в данном случае. Сам же объект разрушается в процессе сбора мусора

9. согласен

10. есть например такой язык objective-c, который используется в продуктах Apple (по сути все не кроссплатформенные приложения для Apple App Store написаны на objective-c), там можно вызвать метод для null объекта и это будет проглочено молча без единного предупреждения, что произойдет? да ничего, просто метод (там это называется событие) не будет вызван. Текущая версия OS поведет себя так же, но я планирую более детально проработать этот момент. Например, в текущий момент при разработке на OS мне очень сильно помогает лог доступа к необъявленым свойсвам и делается это средствами самого же OS. Например, посмотрим файл core.os
function __get(name){
	echo("global property \""name"\" is not declared\n")
	echo "back trace\n"
	printBackTrace(1)
	echo "\n"
}

function Object.__get(name, autoCreate){
	if(autoCreate) return;
	echo("object property \""name"\" is not declared\n")
	echo "back trace\n"
	printBackTrace(1) // skip current function
	echo("=======\ntarget "this"\n\n")
}

function Userdata.__set(name, value){
	echo("userdata property \""name"\" is not declared, set value "value"\n")
	echo "back trace\n"
	printBackTrace(1) // skip current function
	echo("=======\ntarget "this"\n\n")
}

function assert(a, message){
	if(!a){
		print(message || "assert failed")
		printBackTrace(1)
		terminate()
	}
}

setErrorHandler(function(code message file line){
	var type = "ERROR"
	if(code == E_WARNING)
		type = "WARNING"
	else if(code == E_NOTICE)
		type = "NOTICE"
	echo("["type"] "message"\n")
	echo "back trace\n"
	printBackTrace(1) // skip current function
})

function printBackTrace(skipNumFuncs){
	for(var i, t in debugBackTrace(skipNumFuncs + 1)){ // skip printBackTrace
		echo("======= ["i"]\n")
		// echo("  line: "t.line", pos: "t.pos", token: "t.token", file: "t.file"\n")
		echo("  line: "t.line", pos: "t.pos", file: "t.file"\n")
		echo("  function: "t.name", arguments: "t.arguments"\n")
		// print concat("  object: "(t.object === _G && "<<GLOBALS>>" || t.object)"\n")
	}
}

Весь вывод через echo & print перехватывается в виртуальной функции унаследованного от класса ObjectScript и записывается в файл. Таким образом я всегда вижу наличие проблемы, printBackTrace при этом дампит детальный call stack, поэтому я могу понять от куда был вызов и с какими параметрами.
Я могу лишь сказать, что изменение/удаление итератора для стандартных типов (array, object) не приведет к падению, более того отработает как задумано программистом. Но я бы не применял такую практику.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity